123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- /*
- * Copyright 2024 NXP
- * NXP Proprietary. This software is owned or controlled by NXP and may only be used strictly in
- * accordance with the applicable license terms. By expressly accepting such terms or by downloading, installing,
- * activating and/or otherwise using the software, you are agreeing that you have read, and that you agree to
- * comply with and are bound by, such license terms. If you do not agree to be bound by the applicable license
- * terms, then you may not retain, install, activate or otherwise use the software.
- */
- #include <time.h>
- #include <errno.h>
- #include <string.h>
- #include "freemaster_client.h"
- #if LV_USE_GUIDER_SIMULATOR && LV_USE_FREEMASTER
- #include "external_data_init.h"
- #define CALL_RETRY_COUNT 5
- #define DEFAULT_STRING "NULL"
- CURL *ws_connect = NULL;
- lv_obj_t *gg_prompt = NULL;
- extern pthread_mutex_t lvgl_mutex;
- extern pthread_mutex_t jsonrpc_mutex;
- static uint32_t retry_count = 0;
- void connect_init()
- {
- ws_connect = websocket_connect(freemaster_server);
- if (ws_connect == NULL)
- {
- prompt_display("websocket connect failed.");
- return;
- }
- return;
- }
- void freemaster_disconnect()
- {
- if (ws_connect != NULL)
- {
- websocket_close(ws_connect);
- ws_connect = NULL;
- }
- return;
- }
- bool equal_to_double_max(double a)
- {
- /* set the threshold of double type */
- const double epsilon = 1e-9;
- return fabs(fabs(a) - DBL_MAX) / DBL_MAX < epsilon;
- }
- // Release the memory occupied by the string array
- void free_string_array(char **array, int count)
- {
- for (int i = 0; i < count; i++)
- {
- free(array[i]);
- }
- free(array);
- }
- void freeMasterParse(void *param)
- {
- if (strcmp(((readVariableParm *)param)->apiName, "ReadVariable") == 0)
- {
- readVariableParm *user_parm = param;
- char **dataArray = read_variable(user_parm->varArray, user_parm->arrayLen);
- /* use timedlock to avoid dead loop when there is screen transition event*/
- struct timespec timeout = {0, LV_DEF_REFR_PERIOD * 1000 * 1000};
- int err = pthread_mutex_timedlock(&lvgl_mutex, &timeout);
- if (0 != err)
- return;
- /* display the extern data according to widget type. */
- switch (user_parm->widget_type)
- {
- case GG_LABEL:
- {
- lv_label_set_text(user_parm->parentObj, dataArray[0]);
- break;
- }
- case GG_CHART:
- {
- lv_chart_series_t *childObj = NULL;
- for (int i = 0; i < user_parm->arrayLen; i++)
- {
- childObj = (user_parm->childObjArray)[i];
- lv_chart_set_next_value(user_parm->parentObj, childObj, atoi(dataArray[i]));
- }
- lv_chart_refresh(user_parm->parentObj);
- break;
- }
- case GG_BAR:
- {
- lv_bar_set_value(user_parm->parentObj, atoi(dataArray[0]), LV_ANIM_OFF);
- break;
- }
- case GG_METER:
- {
- meter_needle *childObj = NULL;
- for (int i = 0; i < user_parm->arrayLen; i++)
- {
- childObj = (user_parm->childObjArray)[i];
- lv_scale_set_line_needle_value(user_parm->parentObj, childObj->needle_obj, childObj->needle_length, atoi(dataArray[i]));
- }
- break;
- }
- case GG_ARC:
- {
- lv_arc_set_value(user_parm->parentObj, atoi(dataArray[0]));
- break;
- }
- case GG_SLIDER:
- {
- lv_slider_set_value(user_parm->parentObj, atoi(dataArray[0]), LV_ANIM_OFF);
- break;
- }
- case GG_SWITCH:
- {
- if (atoi(dataArray[0]) == 0 && lv_obj_has_state(user_parm->parentObj, LV_STATE_CHECKED))
- {
- lv_obj_clear_state(user_parm->parentObj, LV_STATE_CHECKED);
- }
- if (atoi(dataArray[0]) == 1 && !lv_obj_has_state(user_parm->parentObj, LV_STATE_CHECKED))
- {
- lv_obj_add_state(user_parm->parentObj, LV_STATE_CHECKED);
- }
- break;
- }
- default:
- break;
- }
- free_string_array(dataArray, user_parm->arrayLen);
- pthread_mutex_unlock(&lvgl_mutex);
- }
- return;
- }
- void prompt_display(char *message)
- {
- if (gg_prompt == NULL || !lv_obj_is_valid(gg_prompt))
- {
- gg_prompt = lv_label_create(lv_layer_top()); /* create the prompt label on the top layer */
- lv_label_set_text(gg_prompt, message);
- lv_obj_set_pos(gg_prompt, 0, 0); /* set the prompt label position */
- lv_obj_set_size(gg_prompt, lv_disp_get_hor_res(NULL), 30); /* set the prompt label size */
- lv_label_set_long_mode(gg_prompt, LV_LABEL_LONG_SCROLL); /* set the label text long mode */
- lv_color_t red = lv_color_hex(0xff0027);
- lv_obj_set_style_border_width(gg_prompt, 1, LV_PART_MAIN|LV_STATE_DEFAULT); /* define the font color as yellow */
- lv_obj_set_style_text_color(gg_prompt, red, LV_PART_MAIN | LV_STATE_DEFAULT); /* set the label font color */
- lv_obj_set_style_radius(gg_prompt, 3, LV_PART_MAIN|LV_STATE_DEFAULT);
- }
- }
- json_t *callAPI(json_t* params, char *method_name)
- {
- static uint32_t id = 1;
- json_error_t error;
- json_t *json_obj = NULL;
- json_t *request_data = NULL;
- /* try to connect*/
- if (ws_connect == NULL)
- connect_init();
- /* still unsuccessful? */
- if (ws_connect == NULL)
- return NULL;
- request_data = json_object();
- pthread_mutex_lock(&jsonrpc_mutex);
- /* format the request params json string */
- json_object_set_new(request_data, "jsonrpc", json_string("2.0"));
- json_object_set_new(request_data, "id", json_integer(id));
- json_object_set_new(request_data, "method", json_string(method_name));
- json_object_set_new(request_data, "params", params);
- /* dynamically increase id for jsonrpc request params*/
- id++;
- if (id == UINT_MAX)
- {
- id = 1;
- }
- pthread_mutex_unlock(&jsonrpc_mutex);
- /* Convert JSON object to string */
- char *param_str = json_dumps(request_data, JSON_INDENT(4));
- /* get the json data from FreeMaster server JSONRPC with websocket.*/
- char *origin_response = websocket_request(ws_connect, param_str);
- if (origin_response == NULL)
- {
- fprintf(stderr, "No data returned from jsonrpc server.\n");
- goto err_ret;
- }
- #ifdef DEBUG
- fprintf(stdout, "Decoding json: %s\n", origin_response);
- #endif
- json_obj = json_loads(origin_response, 0, &error);
- if (json_obj == NULL)
- {
- fprintf(stderr, "Failed to decode json: %s\n", error.text);
- goto err_ret;
- }
- err_ret:
- /* Release the JSON object and its string */
- if(request_data)
- json_decref(request_data);
- if(origin_response)
- free(origin_response);
- if(param_str)
- free(param_str);
- return json_obj;
- }
- char **read_variable(fm_var *varArray, int arrayLen)
- {
- json_t *result_json;
- char **dataArray = (char **)malloc(arrayLen * sizeof(char *));
- if (dataArray == NULL)
- {
- return NULL; // malloc failed.
- }
- for (int i = 0; i < arrayLen; i++)
- {
- char *variable_name = varArray[i].varName;
- json_t *params_arr = json_array();
- json_array_append_new(params_arr, json_string(variable_name));
- result_json = callAPI(params_arr, "ReadVariable");
- /* Automatically release the memory occupied by the object when the reference count becomes 0 */
- json_decref(params_arr);
- if (result_json == NULL)
- {
- dataArray[i] = strdup(DEFAULT_STRING);
- continue;
- }
- int success = 0, retval = 0, errorCode = 0;
- char *id, *dataFormatted, *errorMessage = NULL;
- int data;
- json_error_t error;
- int res = json_unpack_ex(result_json, &error, 0, "{s:s, s:{s:b, s?F, s:{s:b, s?:s}, s?{s:i, s:s}}}",
- "id", &id, "result", "success", &success, "data", &data, "xtra", "retval", &retval,
- "formatted", &dataFormatted, "error", "code", &errorCode, "msg", &errorMessage);
- if (res == -1 || !success)
- {
- char * dispaly_error = errorMessage ? errorMessage : error.text;
- retry_count += 1;
- fprintf(stderr, "%s\n", dispaly_error);
- /* retry read the variable when the time over the CALL_RETRT_COUNT will alert the error message. */
- if (retry_count >= CALL_RETRY_COUNT)
- {
- prompt_display(dispaly_error);
- }
- /* call the api failed will be set the default string */
- dataArray[i] = strdup(DEFAULT_STRING);
- continue;
- }
- if (success && res != -1)
- {
- if (lv_obj_is_valid(gg_prompt))
- {
- lv_obj_del(gg_prompt);
- gg_prompt = NULL;
- retry_count = 0;
- }
- }
- dataArray[i] = strdup(dataFormatted);
- if (dataArray[i] == NULL)
- {
- // If memory allocation fails, release the allocated memory and return NULL.
- for (int j = 0; j < i; j++)
- {
- free(dataArray[j]);
- }
- free(dataArray);
- return NULL;
- }
- json_decref(result_json);
- }
- return dataArray;
- }
- void write_variable(char *varName, int value)
- {
- json_t *params_arr = json_array();
- json_array_append_new(params_arr, json_string(varName));
- json_array_append_new(params_arr, json_integer(value));
- callAPI(params_arr, "WriteVariable");
- json_decref(params_arr); /* Automatically release the memory occupied by the object when the reference count becomes 0 */
- return;
- }
- #endif
|