g_object_notify的使用方法

本文介绍了g_object_notify在Gtk窗口管理中的使用方法,包括属性注册、信号发射、信号连接及回调函数实现。通过具体示例代码展示了如何设置窗口模态属性,并在属性变化时触发通知。

g_object_notify的使用方法

0、注册部分

     g_object_class_install_property(gobject_class,

                                                        PROP_MODAL,

               g_param_spec_boolean("modal", P_("Modal"), P_("if true, the window is modal( other windows are not usable while this one is up)"),   FALSE, GTK_PARAM_READWRITE)

                                                       );

1、emit部分

     g_object_notify(G_OBJECT(window), "modal");

// 0,1 两步骤属于属性的注册和信号发射,放在同一个类里。

 

2.  connect部分

     g_signal_connect(window, "notify::modal", G_CALLBACK(notify_modal_received), NULL);

3、回调函数

     void notify_modal_received(GtkWidget *window, GParamSpec *pspec)

     {

         printf("notify modal received");

      }

// 2,3 属于信号获取,可以放在需要的类里


转自:http://socol.iteye.com/blog/532484

#define RESOURCE_LOCK() pthread_mutex_lock(&g_resource_mutex) #define RESOURCE_UNLOCK() pthread_mutex_unlock(&g_resource_mutex) static pthread_mutex_t g_resource_mutex; enum { THREAD_STOPPED = 0, THREAD_RUNNING }; static int ctrl_thread_stat = 0; static int trans_thread_stat[MAX_THREAD_NUM] = {0}; /* 在线升级接口 */ static int start_online_ipc_update(int chn, CHN_UPDATE_INFO *chn_info); int start_online_ipc_update(int chn, CHN_UPDATE_INFO *chn_info) { int res; int fw_ver; if (NULL == chn_info) { dbprintf("param is invalid!\n"); return -1; } /* 连接云服务器,检查最新固件 */ res = UpdateCore_checkFirmwareInfo(chn); if (res < 0) { dbprintf("check failed!\n"); chn_info->update_stat = UPDATE_FAIL; return res; } /* 轮询检查固件检测状态 */ while (TRUE) { sleep(2); res = UpdateCore_getCheckStat(chn, &fw_ver); /* fw_ver为0表示已是最新 */ if (CHECKFW_SUCCESS == res && 0 == fw_ver) { chn_info->update_stat = FW_IS_NEWEST; return 0; } else if (CHECKFW_SUCCESS == res) { break; } else if (CHECKFW_FAILED == res || CHECKFW_OVERTIME == res || ERROR_CHECKFW == res) { chn_info->update_stat = UPDATE_FAIL; return ERROR_CHECKFW; } } /* 下载最新固件进行升级 */ res = UpdateCore_startOnlineUpdate(chn); if (res < 0) { dbprintf("start online update failed!\n"); chn_info->update_stat = UPDATE_FAIL; return res; } chn_info->update_stat = FW_DOWNLOADING; chn_info->fake_rate = 0; int download_count = 0; /* 轮询检查固件下载状态 */ while (TRUE) { sleep(1); download_count++; res = UpdateCore_getOnlineDownloadStat(chn, &chn_info->fake_rate); if (DOWNLOAD_FAILED == res) { chn_info->update_stat = UPDATE_FAIL; return ERROR_DOWNLOADFW; } else if (DOWNLOAD_SUCCESS == res) { chn_info->update_stat = FW_UPDATING; chn_info->fake_rate = 0; break; } else if(CHECKFW_OVERTIME == res) { res = UpdateCore_getCheckStat(chn, &fw_ver); if (CHECKFW_SUCCESS == res && 0 == fw_ver) { chn_info->update_stat = FW_UPDATING; chn_info->fake_rate = 0; break; } } if(download_count > 60) { chn_info->update_stat = UPDATE_FAIL; return ERROR_DOWNLOADFW; } } return 0; } /****************************************************************************** * 函数名称: update_transmit_pthread() * 函数描述: 针对一个channel的回放线程函数 * 输 入:channel_param:见PT_PARAM定义 * 输 出: 无 * 返 回 值: ******************************************************************************/ static void * update_transmit_pthread(void *param) { int i; int ret; int chn; int *thread_stat; CHN_UPDATE_INFO *chn_info; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); prctl(PR_SET_NAME, "update_trans"); thread_stat = (int *)param; *thread_stat = THREAD_RUNNING; while (TRUE) { chn = -1; chn_info = NULL; /* 多线程获取需要升级的通道 */ RESOURCE_LOCK(); for (i = 0; i < IPC_CHANNEL_NUM; i++) { if (g_ipc_updata_data.chn_list[i] && g_ipc_updata_data.chn_update_info[i].update_stat == UPDATE_WAITING) { chn = i; chn_info = &g_ipc_updata_data.chn_update_info[i]; dbprintf("get channel:%d",i); if (LOCAL_UPDATE == g_ipc_updata_data.type) { chn_info->update_stat = FW_DOWNLOADING; } else { chn_info->update_stat = FW_CHECKING; } chn_info->fake_rate = 0; break; } } RESOURCE_UNLOCK(); /* 无需要升级的通道,则退出 */ if (chn < 0) { break; } if (LOCAL_UPDATE == g_ipc_updata_data.type) { /* 调用luci的升级接口 */ dbprintf("chn:%d",chn); ret = UpdateCore_UpdateIPCFirmware(chn + 1, g_ipc_updata_data.file_boundry, g_ipc_updata_data.file_path); chn_info->err_code = ret; chn_info->cur_stat_finish = TRUE; } else if (ONLINE_UPDATE == g_ipc_updata_data.type) { ret = start_online_ipc_update(chn + 1, chn_info); chn_info->err_code = ret; chn_info->fake_rate = 0; } else { /* 不应该出现此状态 */ dbprintf("should exit!\n"); chn_info->update_stat = UPDATE_FAIL; } } *thread_stat = THREAD_STOPPED; return (void *)OK; } /****************************************************************************** * 函数名称: playback_thread() * 函数描述: 回放控制线程,控制播放进度,根据起始时间创建各个channel的子线程 始时间的可能性; * 输 入: playback_parm: 见PLAYBACK_PARM * 输 出: 无 * 返 回 值: ******************************************************************************/ static void * update_control_pthread(void *parm) { int i; int idx = 0; int cnt; char *msg; BOOL need_exit; BOOL refresh_chn_stat; ADDED_DEV_STAT *p_dev = NULL; int last_stat[IPC_CHANNEL_NUM] = {0}; struct blob_buf b; struct ubus_context *ctx = NULL; uint32_t id = 0; int notifyed[IPC_CHANNEL_NUM] = {0}; for (i = 0; i < IPC_CHANNEL_NUM; i++) { last_stat[i] = 1; } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); prctl(PR_SET_NAME, "update_ctrl"); ctrl_thread_stat = THREAD_RUNNING; pthread_mutex_init(&g_resource_mutex, NULL); /* 启动传输线程 */ for (i = 0, idx = 0; i < IPC_CHANNEL_NUM; i++) { if (g_ipc_updata_data.chn_list[i] && g_ipc_updata_data.chn_update_info[i].update_stat == UPDATE_WAITING) { /* 最大同时支持MAX_THREAD_NUM个通道的升级 */ if (idx >= MAX_THREAD_NUM) { break; } if (g_ipc_updata_data.transmit_pthread[idx] == 0 || THREAD_STOPPED == trans_thread_stat[idx]) { if (pthread_create(&(g_ipc_updata_data.transmit_pthread[idx]), NULL, update_transmit_pthread, &trans_thread_stat[idx]) != 0) { perror("transmit_pthread create fail"); g_ipc_updata_data.transmit_pthread[idx] = 0; continue; } idx++; } } } /* 由于升级接口是阻塞的,故每s主动检查 */ while (TRUE) { need_exit = TRUE; refresh_chn_stat = FALSE; for (i = 0; i < IPC_CHANNEL_NUM; i++) { if (g_ipc_updata_data.chn_list[i]) { switch (g_ipc_updata_data.chn_update_info[i].update_stat) { case UPDATE_WAITING: case FW_CHECKING: need_exit = FALSE; break; case FW_DOWNLOADING: /* 本地升级后台创建假进度,在线升级的下载进度通过轮询IPC的接口获得 */ if (LOCAL_UPDATE == g_ipc_updata_data.type) { if (g_ipc_updata_data.chn_update_info[i].cur_stat_finish && g_ipc_updata_data.chn_update_info[i].fake_rate != 100) { /* 状态终止,将进度条更新为100 */ dbprintf("g_ipc_updata_data.chn_update_info[i].cur_stat_finish:%d",g_ipc_updata_data.chn_update_info[i].cur_stat_finish); dbprintf("g_ipc_updata_data.chn_update_info[%d].fake_rate:%d",i,g_ipc_updata_data.chn_update_info[i].fake_rate); g_ipc_updata_data.chn_update_info[i].fake_rate = 100; } else if (g_ipc_updata_data.chn_update_info[i].cur_stat_finish && g_ipc_updata_data.chn_update_info[i].fake_rate == 100) { /* 进度条更新为100后,等待3s进行显示,随后切换为下一个状态 */ g_ipc_updata_data.chn_update_info[i].fake_rate = 0; g_ipc_updata_data.chn_update_info[i].cur_stat_finish = FALSE; if (g_ipc_updata_data.chn_update_info[i].err_code != 0) { g_ipc_updata_data.chn_update_info[i].update_stat = UPDATE_FAIL; } else { g_ipc_updata_data.chn_update_info[i].update_stat = FW_UPDATING; dbprintf("[%d]is FW_UPDATING",i); } } else { /* 上传固件估计需要30s,设置步长为2/s */ g_ipc_updata_data.chn_update_info[i].fake_rate += 4; if (g_ipc_updata_data.chn_update_info[i].fake_rate >= 100) { g_ipc_updata_data.chn_update_info[i].fake_rate = 99; } } } need_exit = FALSE; break; case FW_UPDATING: //调用chm接口通知rtspm IPC已经掉线 if (notifyed[i] == 0) { ctx = ubus_connect(NULL); if (!ctx) { continue; } memset(&b, 0, sizeof(struct blob_buf)); blob_buf_init(&b, 0); blobmsg_add_u32(&b, "channel", i); blobmsg_add_u32(&b, "status", 2); if (!ubus_lookup_id(ctx, "chm_dev_manager", &id)) { ubus_invoke(ctx, id, "chm_dev_manager_conn_status_report", b.head, NULL, NULL, 2 * 1000); } blob_buf_free(&b); if (ctx) { ubus_free(ctx); } notifyed[i] = 1; } if (g_ipc_updata_data.chn_update_info[i].cur_stat_finish && g_ipc_updata_data.chn_update_info[i].fake_rate != 100) { /* 状态终止,将进度条更新为100 */ g_ipc_updata_data.chn_update_info[i].fake_rate = 100; } else if (g_ipc_updata_data.chn_update_info[i].cur_stat_finish && g_ipc_updata_data.chn_update_info[i].fake_rate == 100) { /* 进度条更新为100后,等待2s进行显示,随后切换为下一个状态 */ g_ipc_updata_data.chn_update_info[i].fake_rate = 0; g_ipc_updata_data.chn_update_info[i].cur_stat_finish = FALSE; g_ipc_updata_data.chn_update_info[i].update_stat = UPDATE_SUCCESS; } else if (g_ipc_updata_data.chn_update_info[i].wating_time == 200) { /* 超时 */ dbprintf("time out,channel:%d!\n",i); g_ipc_updata_data.chn_update_info[i].fake_rate = 0; g_ipc_updata_data.chn_update_info[i].cur_stat_finish = FALSE; g_ipc_updata_data.chn_update_info[i].update_stat = UPDATE_FAIL; g_ipc_updata_data.chn_update_info[i].err_code = -3; } else { /* 固件安装的时间认为大约三分钟,每秒步长为0.5/s */ g_ipc_updata_data.chn_update_info[i].fake_rate += 1; g_ipc_updata_data.chn_update_info[i].wating_time += 1; if (g_ipc_updata_data.chn_update_info[i].fake_rate >= 100) { g_ipc_updata_data.chn_update_info[i].fake_rate = 99; } } need_exit = FALSE; refresh_chn_stat = TRUE; break; default: break; } } } if (need_exit) { break; } if (refresh_chn_stat) { /* 获取后台的IPC连接状态,判断固件安装是否完成 */ msg = UpdateCore_doRefreshDevItems(); cnt = UpdateCore_getAddedDevStat(msg, &p_dev); if (cnt > 0 && p_dev) { for (i = 0; i < cnt; i++) { idx = p_dev[i].mChnNo - 1; if (idx < 0) { continue; } if (g_ipc_updata_data.chn_list[idx] && FW_UPDATING == g_ipc_updata_data.chn_update_info[idx].update_stat) { /* 当设备连接状态由不在线变为在线时,代表升级成功 */ if (p_dev[i].mLinkStatus && !last_stat[idx]) { g_ipc_updata_data.chn_update_info[idx].cur_stat_finish = TRUE; } } last_stat[idx] = p_dev[i].mLinkStatus; } free(p_dev); p_dev = NULL; } } sleep(2); } /* 回收资源 */ remove(g_ipc_updata_data.file_path); pthread_mutex_destroy(&g_resource_mutex); ctrl_thread_stat = THREAD_STOPPED; return (void *)OK; } int ipc_update_start() { if (g_ipc_updata_data.control_pthread == 0 || THREAD_STOPPED == ctrl_thread_stat) { if (pthread_create(&(g_ipc_updata_data.control_pthread), NULL, update_control_pthread, NULL) != 0) { perror("create control pthread fail!\n"); return -1; } } return 0; } static int UpdateCore_GetErrorCodeFromJsonRecv(struct json_object *jsonRecv) { int res; struct json_object *jsonData = NULL; struct json_object *jsonErr = NULL; if (jsonRecv == NULL || is_error(jsonRecv)) { dbprintf("%s", "UpdateCore_GetErrorCodeFromJsonRecv: json_tokener_parse failed.\n"); return -1; } jsonData = json_object_object_get(jsonRecv, "result"); if (jsonData == NULL) { dbprintf("json_object_object_get failed %s\n", "result"); res = -1; goto UpdateCore_GetErrorCodeFromJsonRecv_End0; } jsonData = json_object_object_get(jsonData, "responseData"); if (jsonData == NULL) { dbprintf("json_object_object_get failed %s\n", "responseData"); res = -1; goto UpdateCore_GetErrorCodeFromJsonRecv_End0; } jsonErr = json_object_object_get(jsonData, "error_code"); if (jsonErr == NULL) { dbprintf("json_object_object_get failed %s\n", "error_code"); res = -1; } else { res = json_object_get_int(jsonErr); } UpdateCore_GetErrorCodeFromJsonRecv_End0: return res; } int UpdateCore_UpdateIPCFirmware(int chn_idx, char* boundary, char* file_path) { char tmpbuf[5] = {0}; struct json_object *jsonData = NULL; struct json_object *secData= NULL; struct json_object *jsonRecv= NULL; const char* msgSendToLuci = NULL; char* msgRecv = NULL; int res = 0; if (NULL == boundary || NULL == file_path) { return -1; } bzero(tmpbuf, sizeof(tmpbuf)); snprintf(tmpbuf, sizeof(tmpbuf), "%d", chn_idx); secData = create_json_multi_kv(3, "channel", tmpbuf, "filepath", file_path, "mime_boundary", boundary, NULL); jsonData = create_json_do("chm", "ipc_disk_upgrade", secData); msgSendToLuci = json_object_to_json_string(jsonData); PRINT_SENTJSON; /* ����json�� */ msgRecv = jsonCommSendRequest(msgSendToLuci); PRINT_RECVJSON; JSON_FREE(jsonData); /*************** ���鷵��ֵ ***************/ jsonRecv = json_tokener_parse(msgRecv); res = UpdateCore_GetErrorCodeFromJsonRecv(jsonRecv); /* ������ֵΪδ֪���� TpErrorDef_EEXPT -40102������Ϊ�̼��ϴ����� */ if (res == TpErrorDef_EEXPT) { res = ERROR_UPLOADFW; } JSON_FREE(jsonRecv); return res; } char *UpdateCore_doRefreshDevItems() { struct json_object *jsonPara = NULL; struct json_object *jsonData = NULL; const char *pRefresh; const char* msgSendToLuci = NULL; const char *uciName = "chm"; char* msgRecv = NULL; pRefresh = "chm_auto_refresh"; jsonPara = create_json_multi_kv(0, NULL); jsonData = create_json_do(uciName, pRefresh, jsonPara); /* ��json��������json�� */ msgSendToLuci = json_object_to_json_string(jsonData); PRINT_SENTJSON; /* ����json�� */ msgRecv = jsonCommSendRequest(msgSendToLuci); PRINT_RECVJSON; JSON_FREE(jsonData); return msgRecv; } //��ȡ�������豸�����б���������ĸ�����û�з���0���������ظ�ֵ����Ҫ�ͷŷ��ص��ڴ� int UpdateCore_getAddedDevStat(char *jsonMsg, ADDED_DEV_STAT **ppItem) { int res; int i, cnt = 0; ADDED_DEV_STAT *pData = NULL; struct json_object *jsonRecv = NULL; struct json_object *jsonData = NULL; struct json_object *jsonTmp = NULL; struct json_object *jsonOpt = NULL; struct array_list *added_list = NULL; const char *tmpStr; *ppItem = NULL; if (jsonMsg == NULL) { return -1; } /* ���鷵��ֵ */ jsonRecv = json_tokener_parse(jsonMsg); if (!jsonRecv || is_error(jsonRecv)) { return -1; } res = UpdateCore_GetErrorCodeFromJsonRecv(jsonRecv); if (res < 0) { JSON_FREE(jsonRecv); return res; } /* ��ȡresponseData */ jsonData = json_object_object_get(jsonRecv, "result"); if (jsonData == NULL) { cnt = -1; dbprintf("json_object_object_get failed %s\n", "result"); goto UpdateCore_getAddedDevItem_End0; } jsonData = json_object_object_get(jsonData, "responseData"); if (jsonData == NULL) { cnt = -1; dbprintf("json_object_object_get failed %s\n", "responseData"); goto UpdateCore_getAddedDevItem_End0; } jsonData = json_object_object_get(jsonData, "added_list"); if (jsonData == NULL || is_error(jsonData)) { cnt = -1; JSON_FREE(jsonRecv); return cnt; } else { added_list = json_object_get_array(jsonData); if (added_list == NULL) { cnt = -1; goto UpdateCore_getAddedDevItem_End0; } cnt = array_list_length(added_list); if (cnt > 0) { pData = (ADDED_DEV_STAT *)malloc(cnt * sizeof(ADDED_DEV_STAT)); if (pData == NULL) { dbprintf("%s", "NVRCore_getAddedDevItem : malloc failed.\n"); cnt = -1; goto UpdateCore_getAddedDevItem_End0; } bzero(pData, cnt * sizeof(ADDED_DEV_STAT)); *ppItem = pData; for (i = 0; i < cnt; ++i, ++pData) { jsonTmp = (struct json_object *)array_list_get_idx(added_list, i); if (jsonTmp == NULL) { continue; } /* ��ȡͨ��ID */ jsonOpt = json_object_object_get(jsonTmp, "id"); tmpStr = (jsonOpt == NULL) ? "0" : json_object_get_string(jsonOpt); sscanf(tmpStr, "%d", &pData->mChnNo); /* ��ȡͨ������״̬ */ jsonOpt = json_object_object_get(jsonTmp, "online"); tmpStr = (jsonOpt == NULL) ? "0" : json_object_get_string(jsonOpt); sscanf(tmpStr, "%d", &pData->mLinkStatus); } } } UpdateCore_getAddedDevItem_End0: JSON_FREE(jsonRecv); return cnt; } int UpdateCore_checkFirmwareInfo(int chn_idx) { char tmpbuf[5] = {0}; struct json_object *jsonData = NULL; struct json_object *secData= NULL; struct json_object *jsonRecv= NULL; const char* msgSendToLuci = NULL; char* msgRecv = NULL; int res = 0; bzero(tmpbuf, sizeof(tmpbuf)); snprintf(tmpbuf, sizeof(tmpbuf), "%d", chn_idx); secData = create_json_multi_kv(1, "channel", tmpbuf, NULL); jsonData = create_json_do("chm", "online_update_check", secData); msgSendToLuci = json_object_to_json_string(jsonData); PRINT_SENTJSON; /* ����json�� */ msgRecv = jsonCommSendRequest(msgSendToLuci); PRINT_RECVJSON; JSON_FREE(jsonData); /*************** ���鷵��ֵ ***************/ jsonRecv = json_tokener_parse(msgRecv); res = UpdateCore_GetErrorCodeFromJsonRecv(jsonRecv); JSON_FREE(jsonRecv); return res; } int UpdateCore_getCheckStat(int chn_idx, int *fw_ver) { char tmpbuf[5] = {0}; struct json_object *jsonData = NULL; struct json_object *secData= NULL; struct json_object *jsonRecv= NULL; struct json_object *jsonOpt= NULL; const char* msgSendToLuci = NULL; char* msgRecv = NULL; int res = 0; bzero(tmpbuf, sizeof(tmpbuf)); snprintf(tmpbuf, sizeof(tmpbuf), "%d", chn_idx); secData = create_json_multi_kv(1, "channel", tmpbuf, NULL); jsonData = create_json_do("chm", "online_update_check_status", secData); msgSendToLuci = json_object_to_json_string(jsonData); PRINT_SENTJSON; /* ����json�� */ msgRecv = jsonCommSendRequest(msgSendToLuci); PRINT_RECVJSON; JSON_FREE(jsonData); /* ���鷵��ֵ */ jsonRecv = json_tokener_parse(msgRecv); res = UpdateCore_GetErrorCodeFromJsonRecv(jsonRecv); if (res < 0) { res = -1; goto UpdateCore_getCheckStat_End0; } /* ��ȡresponseData */ jsonData = json_object_object_get(jsonRecv, "result"); if (jsonData == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "result"); goto UpdateCore_getCheckStat_End0; } jsonData = json_object_object_get(jsonData, "responseData"); if (jsonData == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "responseData"); goto UpdateCore_getCheckStat_End0; } jsonOpt = json_object_object_get(jsonData, "cloud_config"); if (jsonOpt == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "cloud_status"); goto UpdateCore_getCheckStat_End0; } jsonOpt = json_object_object_get(jsonOpt, "new_firmware"); if (jsonOpt == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "check_fw_ver"); goto UpdateCore_getCheckStat_End0; } /* ��ȡ���״̬ */ jsonOpt = json_object_object_get(jsonOpt, "fw_can_update"); *fw_ver = (jsonOpt == NULL) ? 0 : json_object_get_int(jsonOpt); res = 4; #if 0 jsonOpt = json_object_object_get(jsonData, "cloud_status"); if (jsonOpt == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "cloud_status"); goto UpdateCore_getCheckStat_End0; } jsonOpt = json_object_object_get(jsonOpt, "check_fw_ver"); if (jsonOpt == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "check_fw_ver"); goto UpdateCore_getCheckStat_End0; } /* ��ȡ���״̬ */ jsonOpt = json_object_object_get(jsonOpt, "action_status"); res = (jsonOpt == NULL) ? 3 : json_object_get_int(jsonOpt); /* ״̬��4��ʾ���ɹ� */ if (4 == res) { jsonOpt = json_object_object_get(jsonData, "cloud_config"); if (jsonOpt == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "cloud_config"); goto UpdateCore_getCheckStat_End0; } jsonOpt = json_object_object_get(jsonOpt, "new_firmware"); if (jsonOpt == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "new_firmware"); goto UpdateCore_getCheckStat_End0; } /* ��ȡ���״̬ */ jsonOpt = json_object_object_get(jsonOpt, "fw_new_notify"); *fw_ver = (jsonOpt == NULL) ? 0 : json_object_get_int(jsonOpt); } #endif UpdateCore_getCheckStat_End0: JSON_FREE(jsonRecv); return res; } int UpdateCore_startOnlineUpdate(int chn_idx) { char tmpbuf[5] = {0}; struct json_object *jsonData = NULL; struct json_object *secData= NULL; struct json_object *jsonRecv= NULL; const char* msgSendToLuci = NULL; char* msgRecv = NULL; int res = 0; bzero(tmpbuf, sizeof(tmpbuf)); snprintf(tmpbuf, sizeof(tmpbuf), "%d", chn_idx); secData = create_json_multi_kv(1, "channel", tmpbuf, NULL); jsonData = create_json_do("chm", "online_update", secData); msgSendToLuci = json_object_to_json_string(jsonData); PRINT_SENTJSON; /* ����json�� */ msgRecv = jsonCommSendRequest(msgSendToLuci); PRINT_RECVJSON; JSON_FREE(jsonData); /*************** ���鷵��ֵ ***************/ jsonRecv = json_tokener_parse(msgRecv); res = UpdateCore_GetErrorCodeFromJsonRecv(jsonRecv); JSON_FREE(jsonRecv); return res; } int UpdateCore_getOnlineDownloadStat(int chn_idx, int *rate) { char tmpbuf[5] = {0}; struct json_object *jsonData = NULL; struct json_object *secData= NULL; struct json_object *jsonRecv= NULL; struct json_object *jsonOpt= NULL; const char* msgSendToLuci = NULL; char* msgRecv = NULL; int res = 0; bzero(tmpbuf, sizeof(tmpbuf)); snprintf(tmpbuf, sizeof(tmpbuf), "%d", chn_idx); secData = create_json_multi_kv(1, "channel", tmpbuf, NULL); jsonData = create_json_do("chm", "online_update_progress", secData); msgSendToLuci = json_object_to_json_string(jsonData); PRINT_SENTJSON; /* ����json�� */ msgRecv = jsonCommSendRequest(msgSendToLuci); PRINT_RECVJSON; JSON_FREE(jsonData); /* ���鷵��ֵ */ jsonRecv = json_tokener_parse(msgRecv); res = UpdateCore_GetErrorCodeFromJsonRecv(jsonRecv); //if (res < 0) if(res != 0) { goto UpdateCore_getOnlineDownloadStat_End0; } /* ��ȡresponseData */ jsonData = json_object_object_get(jsonRecv, "result"); if (jsonData == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "result"); goto UpdateCore_getOnlineDownloadStat_End0; } jsonData = json_object_object_get(jsonData, "responseData"); if (jsonData == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "responseData"); goto UpdateCore_getOnlineDownloadStat_End0; } jsonData = json_object_object_get(jsonData, "cloud_status"); if (jsonData == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "cloud_status"); goto UpdateCore_getOnlineDownloadStat_End0; } jsonData = json_object_object_get(jsonData, "client_info"); if (jsonData == NULL) { res = -1; dbprintf("json_object_object_get failed %s\n", "client_info"); goto UpdateCore_getOnlineDownloadStat_End0; } /* ����״̬ */ //jsonOpt = json_object_object_get(jsonData, "fw_download_status"); //res = (jsonOpt == NULL) ? 0 : json_object_get_int(jsonOpt); /* ���ؽ��� */ jsonOpt = json_object_object_get(jsonData, "fw_download_progress"); *rate = (jsonOpt == NULL) ? 0 : json_object_get_int(jsonOpt); if(100 == *rate) { res = 2; } else { res = 1; } UpdateCore_getOnlineDownloadStat_End0: JSON_FREE(jsonRecv); return res; }分析下这段代码,为什么会出现同时本地升级4个设备时,当出现一个设备在安装,其余设备在下载状态时,进度条会卡住,过了一段时间,下载进度条突然到100%,转到安装状态。当都处于安装状态时,安装进度条才会开始变化,第一个进入安装的设备一直卡住。
11-26
假如你是个嵌入式工程师,结合上述测试模块,把如下模块改成amx tr181标准下的实现#include "weather_server.h" #include "log.h" /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* EXTERN_PROTOTYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* LOCAL_PROTOTYPES */ /**************************************************************************************************/ static void ubus_collect_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg); static void ubus_update_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg); static int update_weather_url(void); static int uci_renew(int flag); int uci_get_locationkey(void); const char *uci_get_unit(void); static int uci_set_option(char *uci_section, char *uci_option, char *uci_value); static void weather_timer_cb(struct uloop_timeout *timer); /**************************************************************************************************/ /* VARIABLES */ /**************************************************************************************************/ /* ubus变量 */ static struct ubus_context *ubus_ctx = NULL; static char *ubus_patch; /* uci变量 */ static struct uci_context *uci_ctx = NULL; static struct uci_package *uci_weather = NULL; /* uloop */ struct uloop_timeout timer; /* ubus数据接口结构 */ enum { TEMPERATURE_UNIT, LOCATION_KEY, CITY_NAME, WEATHER_SETTINGS_MAX }; /* ubus参数解析policy */ static const struct blobmsg_policy ubus_policy[] = { [TEMPERATURE_UNIT] = {.name = "temperature_unit", .type = BLOBMSG_TYPE_INT32}, [LOCATION_KEY] = {.name = "location_key", .type = BLOBMSG_TYPE_INT32}, [CITY_NAME] = {.name = "city", .type = BLOBMSG_TYPE_STRING}, }; static struct ubus_event_handler weather_settings_ubus_notify = {.cb = ubus_collect_now}; static struct ubus_event_handler weather_update_ubus_notify = {.cb = ubus_update_now}; /* 更新时间间隔 */ #define DEFAULT_INTERVAL 21600 //6h #define HOURLY_UPDATE_INTERVAL 3600 //1h #define MID_INTERVAL 300 //5min #define FAST_INTERVAL 10 //10s static int renew_interval = DEFAULT_INTERVAL; #define MAX_URL_LEN 256 #define POST_TRANSFER_TIMEOUT 5 #define POST_CONNECT_TIMEOUT 5 #define MAX_TOKEN_LEN 128 /* 相关文件地址 */ #define FILE_CLOUD_TOKEN_WEATHER "/tmp/cloud/cloud_token_weather" #define REALTIME_URL_POSTFIX "/v1/weather/realtime" #define FORECASTS_URL_POSTFIX "/v1/weather/forecasts" #define CA_CRT_PATH "/etc/certificate/2048_newroot.cer" /* * brief 保存post执行结果status code. */ typedef struct _st_http_resinfo { long status_code; }st_http_resinfo; /* * brief 保存当日天气数据. */ struct realtime_weather_info_struct{ int temperature; int temperatureMax; int temperatureMin; int houridx; /* 表示当前为6小时预报数据中的第几个小时 */ char weatherType[10]; struct hourlyForecast{ int temperature; char weatherType[10]; // int datetime; /* 未用到 */ }forecast6Hours[6]; }; static struct realtime_weather_info_struct realtime_weather_info; /* * brief 保存未来三日天气数据. */ struct forecast_weather_info_struct{ int temperatureMax; int temperatureMin; char dayWeatherType[10]; char nightWeatherType[10]; }; static struct forecast_weather_info_struct forecast_weather_info[3]; static int weather_errorcode = 0; /* 云端回传错误代码 */ static char weather_message[20]; /* 云端回传错误信息 */ /**************************************************************************************************/ /* LOCAL_FUNCTIONS */ /**************************************************************************************************/ /* * fn char* Int2String(int num,char *str) * details int转string * * param[in] num:待转换int str:指向转换得到字符串的指针 * param[out] * * return str:指向转换得到字符串的指针 * * note */ char* Int2String(int num,char *str)//10进制 { int i = 0;//指示填充str if(num<0)//如果num为负数,将num变正 { num = -num; str[i++] = '-'; } //转换 do { str[i++] = num%10+48;//取num最低位 字符0~9的ASCII码是48~57;简单来说数字0+48=48,ASCII码对应字符'0' num /= 10;//去掉最低位 }while(num);//num不为0继续循环 str[i] = '\0'; //确定开始调整的位置 int j = 0; if(str[0]=='-')//如果有负号,负号不用调整 { j = 1;//从第二位开始调整 ++i;//由于有负号,所以交换的对称轴也要后移1位 } //对称交换 for(;j<i/2;j++) { //对称交换两端的值 其实就是省下中间变量交换a+b的值:a=a+b;b=a-b;a=a-b; str[j] = str[j] + str[i-1-j]; str[i-1-j] = str[j] - str[i-1-j]; str[j] = str[j] - str[i-1-j]; } return str;//返回转换后的值 } /********************************************ubus相关函数*******************************************/ /* * fn static void weather_ubus_update_event_generate(int flag); * details 通过ubus send将更新得到的天气数据发送给其他相关模块 * * param[in] * param[out] * * return * * note */ static void weather_ubus_update_event_generate(int flag) { static struct blob_buf g_ubus_buf; void *table_len = NULL; time_t timep; struct tm date; blob_buf_init(&g_ubus_buf, 0); time(&timep); /* 获取当前unix时间 */ if(0 == flag) /* 0 == flag,发送当日实时天气数据 */ { date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "realtime"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature" , realtime_weather_info.temperature); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , realtime_weather_info.temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , realtime_weather_info.temperatureMax); blobmsg_add_string(&g_ubus_buf , "weather_type" , realtime_weather_info.weatherType); blobmsg_close_table(&g_ubus_buf, table_len); INFO("[weather_server]: Ubus send realtime weather, renew time:%ld", timep); } else if(1 == flag) /* 1 == flag,发送未来三天天气数据 */ { timep += 86400; /* 调整到后一天同一时刻 */ date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "tomorrow"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , forecast_weather_info[0].temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , forecast_weather_info[0].temperatureMax); blobmsg_add_string(&g_ubus_buf , "day_weather_type" , forecast_weather_info[0].dayWeatherType); blobmsg_add_string(&g_ubus_buf , "night_weather_type" , forecast_weather_info[0].nightWeatherType); blobmsg_close_table(&g_ubus_buf, table_len); timep += 86400; /* 调整到后一天同一时刻 */ date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "2_days_later"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , forecast_weather_info[1].temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , forecast_weather_info[1].temperatureMax); blobmsg_add_string(&g_ubus_buf , "day_weather_type" , forecast_weather_info[1].dayWeatherType); blobmsg_add_string(&g_ubus_buf , "night_weather_type" , forecast_weather_info[1].nightWeatherType); blobmsg_close_table(&g_ubus_buf, table_len); timep += 86400; /* 调整到后一天同一时刻 */ date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "3_days_later"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , forecast_weather_info[2].temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , forecast_weather_info[2].temperatureMax); blobmsg_add_string(&g_ubus_buf , "day_weather_type" , forecast_weather_info[2].dayWeatherType); blobmsg_add_string(&g_ubus_buf , "night_weather_type" , forecast_weather_info[2].nightWeatherType); blobmsg_close_table(&g_ubus_buf, table_len); INFO("[weather_server]: Ubus send forecast weather, renew time:%ld", timep - 86400 * 3); } else /* 2 == flag,发送小时级预报数据 */ { date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "realtime"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature" , realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].temperature); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , realtime_weather_info.temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , realtime_weather_info.temperatureMax); blobmsg_add_string(&g_ubus_buf , "weather_type" , realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].weatherType); blobmsg_close_table(&g_ubus_buf, table_len); INFO("[weather_server]: Ubus send realtime weather, renew time:%ld", timep); DEBUG("houridx:%d,temperature:%d,weather_type:%s",realtime_weather_info.houridx,realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].temperature, realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].weatherType); } /* ubus send event */ ubus_send_event(ubus_ctx, "weather_info_update", g_ubus_buf.head); } /* 清除指定配置项 */ static void uci_del(struct uci_context *p_uci_ctx,const char *section, const char *option) { struct uci_ptr ptr; memset(&ptr, 0, sizeof(struct uci_ptr)); ptr.package = "weather"; ptr.section = section; ptr.option = option; uci_delete(p_uci_ctx, &ptr); return; } /* 清除天气数据 */ static void del_weather_info(void) { struct uci_context *uci_tmpctx = NULL; struct uci_ptr ptr; uci_tmpctx = uci_alloc_context(); if (!uci_tmpctx) { return; } ptr.package = "weather"; ptr.p = uci_lookup_package(uci_tmpctx, "weather"); uci_load(uci_tmpctx, "weather", &ptr.p); uci_del(uci_tmpctx,"realtime","temperature"); uci_del(uci_tmpctx,"realtime","temperatureMax"); uci_del(uci_tmpctx,"realtime","temperatureMin"); uci_del(uci_tmpctx,"realtime","weatherType"); uci_del(uci_tmpctx,"realtime","month"); uci_del(uci_tmpctx,"realtime","day"); uci_del(uci_tmpctx,"tomorrow","temperatureMax"); uci_del(uci_tmpctx,"tomorrow","temperatureMin"); uci_del(uci_tmpctx,"tomorrow","dayWeatherType"); uci_del(uci_tmpctx,"tomorrow","nightWeatherType"); uci_del(uci_tmpctx,"tomorrow","month"); uci_del(uci_tmpctx,"tomorrow","day"); uci_del(uci_tmpctx,"2_days_later","temperatureMax"); uci_del(uci_tmpctx,"2_days_later","temperatureMin"); uci_del(uci_tmpctx,"2_days_later","dayWeatherType"); uci_del(uci_tmpctx,"2_days_later","nightWeatherType"); uci_del(uci_tmpctx,"2_days_later","month"); uci_del(uci_tmpctx,"2_days_later","day"); uci_del(uci_tmpctx,"3_days_later","temperatureMax"); uci_del(uci_tmpctx,"3_days_later","temperatureMin"); uci_del(uci_tmpctx,"3_days_later","dayWeatherType"); uci_del(uci_tmpctx,"3_days_later","nightWeatherType"); uci_del(uci_tmpctx,"3_days_later","month"); uci_del(uci_tmpctx,"3_days_later","day"); uci_commit(uci_tmpctx, &ptr.p, false); uci_free_context(uci_tmpctx); return; } /* * fn static void ubus_collect_now(struct ubus_context *ubus_ctx, * struct ubus_event_handler *ev, * const char *type, struct blob_attr *msg); * details ubus对象方法回调函数,响应ubus send weather_settings_update,更新地理位置参数并立即更新天气信息 * * param[in] * param[out] * * return * * note */ static void ubus_collect_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg) { int status = 0; int temperature_unit = -1; uint32_t location_key = 0; struct blob_attr *tb[WEATHER_SETTINGS_MAX] = {NULL}; char buf[128] = {0}; status = blobmsg_parse(ubus_policy, WEATHER_SETTINGS_MAX, tb, blob_data(msg), blob_len(msg)); if (status < 0) { return; } if (tb[TEMPERATURE_UNIT] && blob_data(tb[TEMPERATURE_UNIT])) { temperature_unit = blobmsg_get_u32(tb[TEMPERATURE_UNIT]); } else { ERR("invalid temperature_unit"); } if (tb[LOCATION_KEY] && blob_data(tb[LOCATION_KEY])) { location_key = blobmsg_get_u32(tb[LOCATION_KEY]); } else { ERR("invalid location_key"); } if (tb[CITY_NAME] && blob_data(tb[CITY_NAME])) { snprintf(buf, sizeof(buf), "%s", blobmsg_get_string(tb[CITY_NAME])); } else { ERR("invalid city_name"); } INFO("[weather_server] Ubus rec: temperature_unit=%d, location_key=%d, city_name=%s",temperature_unit, location_key, buf); del_weather_info(); /* 更新天气信息 */ realtime_weather_info.houridx = 6; /* 小于6会导致不立即从云更新数据 */ weather_timer_cb(&timer); } /* 立即更新天气 */ static void ubus_update_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg) { del_weather_info(); /* 更新天气信息 */ realtime_weather_info.houridx = 6; /* 小于6会导致不立即从云更新数据 */ weather_timer_cb(&timer); } /* * fn static void ubus_reconn_timer(struct uloop_timeout *timeout) * details ubus重连 * * param[in] * param[out] * * return * * note */ static void ubus_reconn_timer(struct uloop_timeout *timeout) { static struct uloop_timeout retry = { .cb = ubus_reconn_timer, }; DEBUG("S:ubus_connection_lost"); if (ubus_reconnect(ubus_ctx, ubus_patch) != 0) { /* 设置每过两秒尝试重连ubusd */ uloop_timeout_set(&retry, 2000); return; } ubus_add_uloop(ubus_ctx); } /* * fn static int weather_ubus_init(char *path) * details ubus初始化 * * param[in] * param[out] * * return * * note */ static int weather_ubus_init(char *path) { ubus_patch = path; /* 连接ubusd */ ubus_ctx = ubus_connect(path); if (!ubus_ctx) { ERR("S:Failed to connect ubusd"); return -1; } /* 设置断线重连回调函数为ubus_reconn_timer */ ubus_ctx->connection_lost = (void (*)(struct ubus_context *))ubus_reconn_timer; DEBUG("S:succeed to connect ubusd"); if (ubus_register_event_handler(ubus_ctx, &weather_settings_ubus_notify, "weather_settings_update") != 0) { ERR("S:Failed to add object to ubusd"); return -1; } if (ubus_register_event_handler(ubus_ctx, &weather_update_ubus_notify, "weather_update") != 0) { ERR("S:Failed to add object to ubusd"); return -1; } /* 向uloop注册 */ ubus_add_uloop(ubus_ctx); DEBUG("S:succeed to add object to ubusd"); return 0; } /* * fn static int weather_ubus_deinit(void) * details 释放ubus变量 * * param[in] * param[out] * * return * * note */ static int weather_ubus_deinit(void) { ubus_unregister_event_handler(ubus_ctx, &weather_settings_ubus_notify); ubus_unregister_event_handler(ubus_ctx, &weather_update_ubus_notify); if(ubus_ctx) { ubus_free(ubus_ctx); } return 0; } /**********************************************天气信息请求*****************************************/ /* * fn static size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid) * details 将从云端收到的数据写入复制到指定字符串中 * * param[in] * param[out] * * return * * note */ static size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid) { unsigned int len = (unsigned int)size * (unsigned int)nmemb; char *str = malloc(len + 1); if (NULL == str || NULL == buffer) { return -1; } char* pData = buffer; memset(str, 0, len + 1); memcpy(str, pData, len); DEBUG("response: %s", str); char **response = lpVoid; *response = str; return len; } /* * fn static size_t cloud_https_post(const char *pUrl, const char *requestHeader, * const char *request, char **response, st_http_resinfo *pHttpResInfo) * details 发送post请求,从云端获取天气数据 * * param[in] * param[out] * * return * * note */ static size_t cloud_https_post(const char *pUrl, const char *requestHeader, const char *request, char **response, st_http_resinfo *pHttpResInfo) { CURLcode res; CURL* curl = NULL; struct curl_slist *headers = NULL; if (NULL == pUrl || NULL == request || NULL == response || NULL == pHttpResInfo) { return CURLE_FAILED_INIT; } DEBUG("pUrl:%s requestHeader:%s request:%s", pUrl, requestHeader, request); res = curl_global_init(CURL_GLOBAL_ALL); if (CURLE_OK != res) { ERR("curl global init fail and ret %d", res); return res; } curl = curl_easy_init(); if (NULL == curl) { res = CURLE_FAILED_INIT; ERR("curl init fail"); goto exit; } // headers = curl_slist_append(headers, "Content-Type: application/json;charset=UTF-8"); headers = curl_slist_append(headers, "Content-Type: application/json"); if (NULL == headers) { ERR("curl get header list fail"); goto exit; } if ((NULL != requestHeader) && (0 < strlen(requestHeader))) { DEBUG("requestHeader is %s", requestHeader); headers = curl_slist_append(headers, requestHeader); if (NULL == headers) { ERR("curl append requestHeader fail"); goto exit; } } //set url // DEBUG("request_url:%s",pUrl); res = curl_easy_setopt(curl, CURLOPT_URL, pUrl); if (CURLE_OK != res) { ERR("curl set option CURLOPT_URL ret %d", res); goto exit; } //set header //DEBUG("request_header:%s",headers); res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); if (CURLE_OK != res) { ERR("curl set option CURLOPT_HTTPHEADER ret %d", res); goto exit; } //set post method res = curl_easy_setopt(curl, CURLOPT_POST, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_POST ret %d", res); goto exit; } // DEBUG("request_data:%s",request); res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request); if (CURLE_OK != res) { ERR("curl set option CURLOPT_POSTFIELDS ret %d", res); goto exit; } //set read/write params res = curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); if (CURLE_OK != res) { ERR("curl set option CURLOPT_READFUNCTION ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post); if (CURLE_OK != res) { ERR("curl set option CURLOPT_WRITEFUNCTION ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response); if (CURLE_OK != res) { ERR("curl set option CURLOPT_WRITEDATA ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_NOSIGNAL ret %d", res); goto exit; } //set certificate info res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_SSL_VERIFYPEER ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_CAINFO, CA_CRT_PATH); if (CURLE_OK != res) { ERR("curl set option CURLOPT_CAINFO ret %d", res); goto exit; } //set CURLOPT_CONNECTTIMEOUT res = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, POST_TRANSFER_TIMEOUT); if (CURLE_OK != res) { ERR("curl set option CURLOPT_CONNECTTIMEOUT ret %d", res); goto exit; } //set CURLOPT_TIMEOUT res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, POST_CONNECT_TIMEOUT); if (CURLE_OK != res) { ERR("curl set option CURLOPT_TIMEOUT ret %d", res); goto exit; } //CURLOPT needs to be set_ FOLLOWLOCATION is 1, otherwise, the data after redirecting will not be returned res = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_FOLLOWLOCATION ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); if (CURLE_OK != res) { ERR("curl set option CURL_SSLVERSION_TLSv1_2 ret %d", res); goto exit; } res = curl_easy_perform(curl); curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &(pHttpResInfo->status_code)); DEBUG("cloud_https_post done. ret %d, http status code %d", res, pHttpResInfo->status_code); exit: if (headers) { curl_slist_free_all(headers); } if (curl) { curl_easy_cleanup(curl); } curl_global_cleanup(); return res; } /* * fn int get_token_url(char *token, char *url) * details 获取device token和云端天气预报请求url * * param[in] * param[out] * * return * * note */ int get_token_url(char *token, char *url) { int ret = -1; int retry_count = 3; FILE *fp = NULL; while (retry_count > 0) { if((fp = fopen(FILE_CLOUD_TOKEN_WEATHER, "r"))) { fscanf(fp, "%s", token); fscanf(fp, "%s", url); fclose(fp); ret = 0; break; } else { system("cloud_getDevToken weather"); } retry_count--; } return ret; } /* * fn static int set_weather_cloud_request_data(char *device_token, char *request_data) * details 读取uci配置中的location_key,与输入参数device_token共同构造post请求参数 * * param[in] char *device_token 从云端获取的device token * char *request_data 存储post请求参数字符串 * param[out] * * return * * note */ static int set_weather_cloud_request_data(char *device_token, char *request_data) { //int ret = -1; json_object* request_data_json = NULL; const char* request_data_out = NULL; //FILE *fp = NULL; int locationkey = 0; locationkey = uci_get_locationkey(); if ( -1 == locationkey) { ERR("uci_get_locationkey failed"); return -1; } if ((request_data_json = json_object_new_object()) == NULL) { return -1; } json_object_object_add(request_data_json, "locationKey", json_object_new_int(locationkey)); json_object_object_add(request_data_json, "deviceToken", json_object_new_string(device_token)); request_data_out = json_object_to_json_string(request_data_json); memcpy(request_data, request_data_out, strlen(request_data_out)); if (request_data_json) { json_object_put(request_data_json); } return 0; } /* * fn int get_realtime_info_from_cloud(struct realtime_weather_info_struct *realtime_weather_info, * char *device_token, char *url_prefix) * details 从云端获取当日天气数据并解析 * * param[in] struct realtime_weather_info_struct *realtime_weather_info 存储当日天气数据结构体 * char *device_token 从云端获取的device token * char *url_prefix 云端请求天气数据url前缀 * param[out] * * return ret 0表示获取数据成功,-1表示失败 * * note */ int get_realtime_info_from_cloud(struct realtime_weather_info_struct *realtime_weather_info, char *device_token, char *url_prefix) { int ret = -1; int i = 0; char request_url[128] = {0}; char request_header[64] = {0}; char tmpstr[40] = {0}; char request_data[512] = {0}; char *response = ""; st_http_resinfo httpResInfo; json_object* response_json = NULL; json_object* errorcode = NULL; json_object* message = NULL; json_object* result = NULL; json_object* temperature = NULL; json_object* temperatureMax = NULL; json_object* temperatureMin = NULL; json_object* weatherType = NULL; json_object* forecast6Hours = NULL; json_object* hourlyForecats = NULL; int errorcode_data = -1; const char* message_data = NULL; int temperature_data = -1; int temperatureMax_data = -1; int temperatureMin_data = -1; int hourlyTemperature_data[6] = {0}; const char* weatherType_data = NULL; const char* hourlyWeatherType_data[6] = {NULL}; if (realtime_weather_info == NULL || device_token == NULL || url_prefix == NULL) { ERR("params error"); ret = -1; goto exit; } memset(&httpResInfo, 0, sizeof(st_http_resinfo)); sprintf(request_url, "%s%s", url_prefix, REALTIME_URL_POSTFIX); if (-1 == set_weather_cloud_request_data(device_token, request_data)) { ERR("set_weather_cloud_request_data error"); ret = -1; goto exit; } //get post result cloud_https_post(request_url, request_header, request_data, &response, &httpResInfo); DEBUG("httpResInfo.status_code:%ld",httpResInfo.status_code); DEBUG("response:%s",response); if (response && httpResInfo.status_code == 200) { response_json = json_tokener_parse(response); errorcode = json_object_object_get(response_json, "code"); errorcode_data = json_object_get_int(errorcode); if (0 != errorcode_data) { weather_errorcode = errorcode_data; sprintf(tmpstr, "get weather info errorcode:%d", errorcode_data); // uci_set_option("global", "error", tmpstr); ret = -1; goto exit; } message = json_object_object_get(response_json, "message"); result = json_object_object_get(response_json, "result"); temperature = json_object_object_get(result, "temperature"); temperatureMax = json_object_object_get(result, "temperatureMax"); temperatureMin = json_object_object_get(result, "temperatureMin"); weatherType = json_object_object_get(result, "weatherType"); message_data = json_object_get_string(message); temperature_data = json_object_get_int(temperature); temperatureMax_data = json_object_get_int(temperatureMax); temperatureMin_data = json_object_get_int(temperatureMin); weatherType_data = json_object_get_string(weatherType); forecast6Hours = json_object_object_get(result, "forecast6Hours"); if ( json_type_array != json_object_get_type(forecast6Hours) || 6 != json_object_array_length(forecast6Hours) ) { ret = -1; goto exit; } for ( i = 0; i < 6; i++) { hourlyForecats = json_object_array_get_idx(forecast6Hours, i); temperature = json_object_object_get(hourlyForecats, "temperature"); weatherType = json_object_object_get(hourlyForecats, "weatherType"); hourlyTemperature_data[i] = json_object_get_int(temperature); hourlyWeatherType_data[i] = json_object_get_string(weatherType); } if (0 == errorcode_data && message_data && weatherType_data) { DEBUG("errorcode : %d", errorcode_data); DEBUG("message : %s", message_data); DEBUG("temperature : %d", temperature_data); DEBUG("temperatureMax : %d", temperatureMax_data); DEBUG("temperatureMin : %d", temperatureMin_data); DEBUG("weatherType : %s", weatherType_data); // tmpstr = uci_get_unit(); // DEBUG("unit:%s",tmpstr); if (0 == strcmp(uci_get_unit(),"centigrade")) { realtime_weather_info->temperature = (temperature_data - 32) / 1.8; realtime_weather_info->temperatureMax = (temperatureMax_data -32) / 1.8; realtime_weather_info->temperatureMin = (temperatureMin_data - 32) / 1.8; for ( i = 0; i < 6; i++) { realtime_weather_info->forecast6Hours[i].temperature = (hourlyTemperature_data[i] - 32) / 1.8; DEBUG("%d:temperature:%d\n",i,realtime_weather_info->forecast6Hours[i].temperature); } } else { realtime_weather_info->temperature = temperature_data; realtime_weather_info->temperatureMax = temperatureMax_data; realtime_weather_info->temperatureMin = temperatureMin_data; for ( i = 0; i < 6; i++) { realtime_weather_info->forecast6Hours[i].temperature = hourlyTemperature_data[i]; DEBUG("%d:temperature:%d\n",i,realtime_weather_info->forecast6Hours[i].temperature); } } sprintf(realtime_weather_info->weatherType, "%s", weatherType_data); for ( i = 0; i < 6; i++) { sprintf(realtime_weather_info->forecast6Hours[i].weatherType, "%s", hourlyWeatherType_data[i]); DEBUG("%d:weatherType:%s\n",i,realtime_weather_info->forecast6Hours[i].weatherType); } weather_errorcode = errorcode_data; memcpy(weather_message, message_data, strlen(message_data)); ret = 0; } } else { // uci_set_option("global", "error", "cloud_https_post failed"); ret = -1; } exit: if (response_json) { json_object_put(response_json); } if (errorcode) { json_object_put(errorcode); } if (message) { json_object_put(message); } if (result) { json_object_put(result); } if (temperature) { json_object_put(temperature); } if (temperatureMax) { json_object_put(temperatureMax); } if (temperatureMin) { json_object_put(temperatureMin); } if (weatherType) { json_object_put(weatherType); } if (forecast6Hours) { json_object_put(forecast6Hours); } if (hourlyForecats) { json_object_put(hourlyForecats); } return ret; } /* * fn int get_forecast_info_from_cloud(struct forecast_weather_info_struct *forecast_weather_info, * char *device_token, char *url_prefix) * details 从云端获取未来三天天气数据并解析 * * param[in] struct forecast_weather_info_struct *forecast_weather_info 存储未来三天天气数据结构体 * char *device_token 从云端获取的device token * char *url_prefix 云端请求天气数据url前缀 * param[out] * * return ret 0表示获取数据成功,-1表示失败 * * note */ int get_forecast_info_from_cloud(struct forecast_weather_info_struct *forecast_weather_info, char *device_token, char *url_prefix) { int ret = -1; // int ret_post = 0; int i = 0; char request_url[128] = {0}; char request_header[64] = {0}; char tmpstr[40] = {0}; char request_data[512] = {0}; char *response = NULL; st_http_resinfo httpResInfo; json_object* response_json = NULL; json_object* errorcode = NULL; json_object* message = NULL; json_object* result = NULL; json_object* forecastList = NULL; json_object* ListItem = NULL; json_object* temperatureMax = NULL; json_object* temperatureMin = NULL; json_object* dayWeatherType = NULL; json_object* nightWeatherType = NULL; int errorcode_data = -1; const char* message_data = NULL; int temperatureMax_data = -1; int temperatureMin_data = -1; const char* dayWeatherType_data = NULL; const char* nightWeatherType_data = NULL; if (forecast_weather_info == NULL || device_token == NULL || url_prefix == NULL) { ERR("params error"); ret = -1; goto exit; } memset(&httpResInfo, 0, sizeof(st_http_resinfo)); sprintf(request_url, "%s%s", url_prefix, FORECASTS_URL_POSTFIX); if (-1 == set_weather_cloud_request_data(device_token, request_data)) { ERR("set_weather_cloud_request_data error"); ret = -1; goto exit; } //get post result cloud_https_post(request_url, request_header, request_data, &response, &httpResInfo); DEBUG("httpResInfo.status_code:%ld",httpResInfo.status_code); DEBUG("response:%s",response); if (response && httpResInfo.status_code == 200) { response_json = json_tokener_parse(response); errorcode = json_object_object_get(response_json, "code"); errorcode_data = json_object_get_int(errorcode); if (0 != errorcode_data) { weather_errorcode = errorcode_data; sprintf(tmpstr, "get weather info errorcode:%d", errorcode_data); // uci_set_option("global", "error", tmpstr); ret = -1; goto exit; } message = json_object_object_get(response_json, "message"); result = json_object_object_get(response_json, "result"); forecastList = json_object_object_get(result, "forecastList"); message_data = json_object_get_string(message); if (0 == errorcode_data && message_data) { DEBUG("errorcode : %d", errorcode_data); DEBUG("message : %s", message_data); for ( i = 0; i < 3; i++) { ListItem = json_object_array_get_idx(forecastList,i); temperatureMax = json_object_object_get(ListItem, "temperatureMax"); temperatureMin = json_object_object_get(ListItem, "temperatureMin"); dayWeatherType = json_object_object_get(ListItem, "dayWeatherType"); nightWeatherType = json_object_object_get(ListItem, "nightWeatherType"); temperatureMax_data = json_object_get_int(temperatureMax); temperatureMin_data = json_object_get_int(temperatureMin); dayWeatherType_data = json_object_get_string(dayWeatherType); nightWeatherType_data = json_object_get_string(nightWeatherType); DEBUG("temperatureMax : %d", temperatureMax_data); DEBUG("temperatureMin : %d", temperatureMin_data); DEBUG("dayWeatherType : %s", dayWeatherType_data); DEBUG("nightWeatherType : %s", nightWeatherType_data); if (dayWeatherType_data && nightWeatherType_data) { // tmpstr = uci_get_unit(); // DEBUG("unit:%s",tmpstr); if (0 == strcmp(uci_get_unit(),"centigrade")) { forecast_weather_info[i].temperatureMax = (temperatureMax_data - 32) / 1.8; forecast_weather_info[i].temperatureMin = (temperatureMin_data - 32) / 1.8; } else { forecast_weather_info[i].temperatureMax = temperatureMax_data; forecast_weather_info[i].temperatureMin = temperatureMin_data; } sprintf(forecast_weather_info[i].dayWeatherType, "%s", dayWeatherType_data); sprintf(forecast_weather_info[i].nightWeatherType, "%s", nightWeatherType_data); } } weather_errorcode = errorcode_data; memcpy(weather_message, message_data, strlen(message_data)); ret = 0; } } else { // uci_set_option("global", "error", "cloud_https_post failed"); ret = -1; } exit: if (response_json) { json_object_put(response_json); } if (errorcode) { json_object_put(errorcode); } if (message) { json_object_put(message); } if (result) { json_object_put(result); } if (forecastList) { json_object_put(forecastList); } if (ListItem) { json_object_put(ListItem); } if (temperatureMax) { json_object_put(temperatureMax); } if (temperatureMin) { json_object_put(temperatureMin); } if (dayWeatherType) { json_object_put(dayWeatherType); } if (nightWeatherType) { json_object_put(nightWeatherType); } return ret; } /* * fn static int update_weather_url(void) * details 更新天气数据 * * param[in] * param[out] * * return 0表示获取数据成功,-1表示失败 * * note */ static int update_weather_url(void) { char device_token[MAX_TOKEN_LEN] = {0}; char cloud_weather_url[MAX_URL_LEN] = {0}; int i = 0; /* init */ realtime_weather_info.temperature = 0; realtime_weather_info.temperatureMax = 0; realtime_weather_info.temperatureMin = 0; memset(realtime_weather_info.weatherType, 0, sizeof(realtime_weather_info.weatherType)); for ( i = 0; i < 6; i++) { realtime_weather_info.forecast6Hours[i].temperature = 0; // realtime_weather_info.forecast6Hours[i].datetime = 0; memset(realtime_weather_info.forecast6Hours[i].weatherType, 0, sizeof(realtime_weather_info.weatherType)); } for ( i = 0; i < 3; i++) { forecast_weather_info[i].temperatureMax = 0; forecast_weather_info[i].temperatureMin = 0; memset(forecast_weather_info[i].dayWeatherType, 0, sizeof(forecast_weather_info[i].dayWeatherType)); memset(forecast_weather_info[i].nightWeatherType, 0, sizeof(forecast_weather_info[i].nightWeatherType)); } /* online request */ if (0 == (get_token_url(device_token, cloud_weather_url))) { /* get_realtime_info_from_cloud */ if (0 == get_realtime_info_from_cloud(&realtime_weather_info, device_token, cloud_weather_url)) { weather_ubus_update_event_generate(0); if (1 != uci_renew(0)) { ERR("set_realtime_info_to_uci fail"); // uci_set_option("global", "error", "set_realtime_info_to_uci fail"); return -1; } realtime_weather_info.houridx = 0; /* 重置当前小时数 */ DEBUG("get_realtime_info_from_cloud succeed"); } else { WARNING("get_realtime_info_from_cloud error"); return -1; } /* get_forecast_info_from_cloud */ if (0 == get_forecast_info_from_cloud(forecast_weather_info, device_token, cloud_weather_url)) { weather_ubus_update_event_generate(1); if (1 != uci_renew(1)) { ERR("set_forecast_info_to_uci fail"); // uci_set_option("global", "error", "set_forecast_info_to_uci fail"); return -1; } DEBUG("get_forecast_info_from_cloud succeed"); } else { WARNING("get_forecast_info_from_cloud error"); return -1; } } else { ERR("get_token_url error"); return -1; } return 0; } /**********************************************uci相关函数******************************************/ /* * fn static void config_free(void) * details uci变量释放 * * param[in] * param[out] * * return * * note */ static void config_free(void) { if (uci_weather) { uci_unload(uci_ctx, uci_weather); uci_weather = NULL; } if (uci_ctx) { uci_free_context(uci_ctx); uci_ctx = NULL; } } /* * fn static struct uci_package *config_init_package(char *config) * details 获取uci文件package * * param[in] * param[out] * * return * * note */ static struct uci_package *config_init_package(char *config) { struct uci_package *p = NULL; if (!uci_ctx) { /* 申请uci上下文结构uci_ctx */ uci_ctx = uci_alloc_context(); // uci_ctx->flags &= ~UCI_FLAG_STRICT; } else { /* 查找config文件 */ p = uci_lookup_package(uci_ctx, config); if (p) { uci_unload(uci_ctx, p); } DEBUG("S:uci_unload"); } /* 加载配置到内存 */ if ( UCI_OK != uci_load(uci_ctx, config, &p) ) { p = NULL; DEBUG("S:uci load error"); } return p; } /* * fn static int config_alloc(void) * details 获取uci文件package,地址保存到全局变量uci_weather中 * * param[in] * param[out] * * return * * note */ static int config_alloc(void) { uci_weather = config_init_package("weather"); if (!uci_weather) { ERR("S:Failed to load weather config"); return 0; } DEBUG("S:succeed to load weather config"); return 1; } /* * fn static int uci_init(void) * details uci初始化 * * param[in] * param[out] * * return * * note */ static int uci_init(void) { struct uci_section *tmp_sec; /* 获取uci配置文件 */ if( !config_alloc()) { ERR("S:config_alloc error"); config_free(); return 0; } /* 检查uci配置文件中的section */ tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "global"); if ( !tmp_sec) { ERR("S:lookup global section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "realtime"); if ( !tmp_sec) { ERR("S:lookup realtime section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "forecast"); if ( !tmp_sec) { ERR("S:lookup forecast section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "tomorrow"); if ( !tmp_sec) { ERR("S:lookup forecast1 section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "2_days_later"); if ( !tmp_sec) { ERR("S:lookup forecast2 section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "3_days_later"); if ( !tmp_sec) { ERR("S:lookup forecast3 section failed"); config_free(); return 0; } return 1; } /* * fn static int uci_set_option(char *uci_section, char *uci_option, char *uci_value) * details 配置uci配置文件option * * param[in] char *uci_section section名 * char *uci_option option的key, * char *uci_value option的value * param[out] * * return * * note */ static int uci_set_option(char *uci_section, char *uci_option, char *uci_value) { int ret = 0; struct uci_ptr ptr ={ .package = "weather", .section = uci_section, .option = uci_option, .value = uci_value }; /* 配置uci配置文件option,key=uci_option,value=uci_value*/ ret = uci_set(uci_ctx, &ptr); if( UCI_OK != ret) { ERR("S:set %s failed",uci_option); return 0; } // DEBUG("S:set %s ok",uci_option); /* 保存配置 */ uci_save(uci_ctx, ptr.p); uci_commit(uci_ctx, &ptr.p, false); return 1; } /* * fn int uci_get_locationkey(void) * details 从uci配置文件中读取locationkey * * param[in] * param[out] * * return key 从uci配置文件中读取的locationkey * * note */ int uci_get_locationkey(void) { int key = 0; const char *key_str = NULL; struct uci_context *tmpCtx = NULL; struct uci_package *tmppkg = NULL; struct uci_section *tmpsec = NULL; tmpCtx = uci_alloc_context(); if ( UCI_OK != uci_load(tmpCtx, "weather", &tmppkg) ) { // uci_set_option("global", "error", "uci_load weather error"); ERR("S:uci load error"); key = -1; goto exit; } tmpsec = uci_lookup_section(tmpCtx, tmppkg, "global"); if ( !tmpsec) { // uci_set_option("global", "error", "lookup global section failed"); ERR("S:lookup global section failed"); key = -1; goto exit; } key_str = uci_lookup_option_string(tmpCtx, tmpsec, "location_key"); if(!key_str) { // uci_set_option("global", "error", "lookup location_key option failed"); ERR("S:lookup location_key option failed"); key = -1; goto exit; } key = atoi(key_str); DEBUG("uci_get_option location_key:%d",key); exit: uci_unload(tmpCtx, tmppkg); uci_free_context(tmpCtx); return key; } /* * fn const char *uci_get_unit(void) * details 从uci配置文件中读取temperature_unit * * param[in] * param[out] * * return unit_str 从uci配置文件中读取的temperature_unit * * note */ const char *uci_get_unit(void) { const char *unit_str = NULL; struct uci_context *tmpCtx = NULL; struct uci_package *tmppkg = NULL; struct uci_section *tmpsec = NULL; tmpCtx = uci_alloc_context(); if ( UCI_OK != uci_load(tmpCtx, "weather", &tmppkg) ) { // uci_set_option("global", "error", "uci_load weather error"); ERR("S:uci load error"); goto exit; } tmpsec = uci_lookup_section(tmpCtx, tmppkg, "global"); if ( !tmpsec) { // uci_set_option("global", "error", "lookup global section failed"); ERR("S:lookup global section failed"); goto exit; } unit_str = uci_lookup_option_string(tmpCtx, tmpsec, "temperature_unit"); if(!unit_str) { // uci_set_option("global", "error", "lookup unit option failed"); unit_str = "fahrenheit"; /* 如果配置缺失,默认华氏度 */ ERR("S:lookup unit option failed"); goto exit; } exit: uci_unload(tmpCtx, tmppkg); uci_free_context(tmpCtx); return unit_str; } /* * fn static void uci_renew(int flag) * details 将从云端拿到的天气数据写入uci配置文件, * * param[in] int flag 为0时表示写入当日天气数据,为1时表示写入未来三天天气数据 * param[out] * * return 0表示写入失败,1表示写入成功 * * note */ static int uci_renew(int flag) { time_t timep; struct tm date; // char time_cu[10] = ""; char section[20] = ""; char tmpstr[20] = ""; int i = 0; /* 获取当前unix时间 */ time(&timep); /* 配置uci配置文件对应option */ if (0 == flag) { /* 更新实时天气信息 */ date = * (localtime(&timep)); if (1 != uci_set_option("realtime", "errorcode", Int2String(weather_errorcode,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "message", weather_message)) { return 0; } if (1 != uci_set_option("realtime", "time_renew", Int2String((int)timep,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "month", Int2String(date.tm_mon + 1,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "day", Int2String(date.tm_mday,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "temperature", Int2String(realtime_weather_info.temperature,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "temperatureMax", Int2String(realtime_weather_info.temperatureMax,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "temperatureMin", Int2String(realtime_weather_info.temperatureMin,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "weatherType", realtime_weather_info.weatherType)) { return 0; } DEBUG("S:realtime weather uci renew time:%ld", timep); } else { /* 更新预报天气信息 */ if (1 != uci_set_option("forecast", "errorcode", Int2String(weather_errorcode,tmpstr))) { return 0; } if (1 != uci_set_option("forecast", "message", weather_message)) { return 0; } if (1 != uci_set_option("forecast", "time_renew", Int2String((int)timep,tmpstr))) { return 0; } for (i = 0; i < 3; i++) { timep += 86400; /* 调整到后一天同一时刻 */ date = * (localtime(&timep)); if (0 == i) { sprintf(section,"tomorrow"); } else { sprintf(section,"%d_days_later",i + 1); } if (1 != uci_set_option(section, "temperatureMax", Int2String(forecast_weather_info[i].temperatureMax,tmpstr))) { return 0; } if (1 != uci_set_option(section, "temperatureMin", Int2String(forecast_weather_info[i].temperatureMin,tmpstr))) { return 0; } if (1 != uci_set_option(section, "dayWeatherType", forecast_weather_info[i].dayWeatherType)) { return 0; } if (1 != uci_set_option(section, "nightWeatherType", forecast_weather_info[i].nightWeatherType)) { return 0; } if (1 != uci_set_option(section, "month", Int2String(date.tm_mon + 1,tmpstr))) { return 0; } if (1 != uci_set_option(section, "day", Int2String(date.tm_mday,tmpstr))) { return 0; } } DEBUG("S:forecast weather uci renew time:%ld", timep - 86400 * 3); } return 1; } /**********************************************定时控制函数*****************************************/ /* * fn static void weather_timer_cb(struct uloop_timeout *timer) * details 定时更新天气数据,renew_interval控制下次更新时间间隔 * * param[in] * param[out] * * return * * note */ static void weather_timer_cb(struct uloop_timeout *timer) { if ( 6 <= realtime_weather_info.houridx ) { if (HOURLY_UPDATE_INTERVAL == renew_interval) { renew_interval = DEFAULT_INTERVAL; /* 兼容原有逻辑,否则更新失败时renew_interval=2h */ } if (0 != update_weather_url()) { ERR("S:update_weather_url failed"); if (DEFAULT_INTERVAL == renew_interval) { if (-20652 == weather_errorcode) { system("rm /tmp/cloud/cloud_token_weather"); /* devicetoken失效 */ renew_interval = FAST_INTERVAL; /* 10s后重试 */ } else { renew_interval = MID_INTERVAL; /* 5min后重试 */ } } else if(DEFAULT_INTERVAL > renew_interval * 2) { renew_interval *= 2; /* 重试时间*2 */ } else { renew_interval = DEFAULT_INTERVAL + 1; /* 最高时间间隔6h+1s,多1s防止误判,否则再次失败renew_interval又会缩短 */ } } else { // renew_interval = DEFAULT_INTERVAL; /* 成功后时间恢复6h */ renew_interval = HOURLY_UPDATE_INTERVAL; /* 成功后开始每小时更新 */ } } else { weather_ubus_update_event_generate(2); realtime_weather_info.houridx++; renew_interval = HOURLY_UPDATE_INTERVAL; /* 1h后刷新数据 */ } DEBUG("Period CallBack"); uloop_timeout_set(timer, renew_interval * 1000); } /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ /**************************************************************************************************/ /* GLOBAL_FUNCTIONS */ /**************************************************************************************************/ int main() { char *ubus_socket = NULL; // unsigned int seed; /* 随机种子 */ // int fd = -1; char buf[20] = ""; FILE *fp = NULL; realtime_weather_info.houridx = 6; /* 如果小于6会导致模块刚启动时不更新天气 */ memset(&timer, 0, sizeof(timer)); /* ubus初始化 */ uloop_init(); if (-1 == weather_ubus_init(ubus_socket)) { ERR("S:weather_ubus_init failed"); } /* uci初始化 */ if (0 == uci_init()) { ERR("S:uci_init failed"); } /* 通过ntp检查网络状态,后续断网导致的更新失败由原有的重试机制处理 */ while(1) { if ( (fp = fopen("/tmp/state/systime", "r") ) != NULL) { fgets(buf, 20, fp); fgets(buf, 20, fp); /* 连续读取两次以获取文件第二行内容 */ if ( 49 == buf[18] ) /* 如果systime.core.sync=1 */ { fclose(fp); break; } else { ERR("weather detect ntp not sync\n"); } fclose(fp); } sleep(10); } /* 配置定时更新函数 */ timer.cb = weather_timer_cb; uloop_timeout_set(&timer, 0); /* uloop启动 */ DEBUG("S:uloop_run start"); uloop_run(); DEBUG("S:uloop_run end"); /*uci变量释放*/ config_free(); /* curl释放*/ curl_global_cleanup(); /* ubus释放*/ weather_ubus_deinit(); uloop_done(); DEBUG("S:uloop_done"); return 0; }
最新发布
12-16
修改如下为同风格使用amx,TR-181 数据模型#include "weather_server.h" #include "log.h" /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* EXTERN_PROTOTYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* LOCAL_PROTOTYPES */ /**************************************************************************************************/ static void ubus_collect_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg); static void ubus_update_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg); static int update_weather_url(void); static int uci_renew(int flag); int uci_get_locationkey(void); const char *uci_get_unit(void); static int uci_set_option(char *uci_section, char *uci_option, char *uci_value); static void weather_timer_cb(struct uloop_timeout *timer); /**************************************************************************************************/ /* VARIABLES */ /**************************************************************************************************/ /* ubus变量 */ static struct ubus_context *ubus_ctx = NULL; static char *ubus_patch; /* uci变量 */ static struct uci_context *uci_ctx = NULL; static struct uci_package *uci_weather = NULL; /* uloop */ struct uloop_timeout timer; /* ubus数据接口结构 */ enum { TEMPERATURE_UNIT, LOCATION_KEY, CITY_NAME, WEATHER_SETTINGS_MAX }; /* ubus参数解析policy */ static const struct blobmsg_policy ubus_policy[] = { [TEMPERATURE_UNIT] = {.name = "temperature_unit", .type = BLOBMSG_TYPE_INT32}, [LOCATION_KEY] = {.name = "location_key", .type = BLOBMSG_TYPE_INT32}, [CITY_NAME] = {.name = "city", .type = BLOBMSG_TYPE_STRING}, }; static struct ubus_event_handler weather_settings_ubus_notify = {.cb = ubus_collect_now}; static struct ubus_event_handler weather_update_ubus_notify = {.cb = ubus_update_now}; /* 更新时间间隔 */ #define DEFAULT_INTERVAL 21600 //6h #define HOURLY_UPDATE_INTERVAL 3600 //1h #define MID_INTERVAL 300 //5min #define FAST_INTERVAL 10 //10s static int renew_interval = DEFAULT_INTERVAL; #define MAX_URL_LEN 256 #define POST_TRANSFER_TIMEOUT 5 #define POST_CONNECT_TIMEOUT 5 #define MAX_TOKEN_LEN 128 /* 相关文件地址 */ #define FILE_CLOUD_TOKEN_WEATHER "/tmp/cloud/cloud_token_weather" #define REALTIME_URL_POSTFIX "/v1/weather/realtime" #define FORECASTS_URL_POSTFIX "/v1/weather/forecasts" #define CA_CRT_PATH "/etc/certificate/2048_newroot.cer" /* * brief 保存post执行结果status code. */ typedef struct _st_http_resinfo { long status_code; }st_http_resinfo; /* * brief 保存当日天气数据. */ struct realtime_weather_info_struct{ int temperature; int temperatureMax; int temperatureMin; int houridx; /* 表示当前为6小时预报数据中的第几个小时 */ char weatherType[10]; struct hourlyForecast{ int temperature; char weatherType[10]; // int datetime; /* 未用到 */ }forecast6Hours[6]; }; static struct realtime_weather_info_struct realtime_weather_info; /* * brief 保存未来三日天气数据. */ struct forecast_weather_info_struct{ int temperatureMax; int temperatureMin; char dayWeatherType[10]; char nightWeatherType[10]; }; static struct forecast_weather_info_struct forecast_weather_info[3]; static int weather_errorcode = 0; /* 云端回传错误代码 */ static char weather_message[20]; /* 云端回传错误信息 */ /**************************************************************************************************/ /* LOCAL_FUNCTIONS */ /**************************************************************************************************/ /* * fn char* Int2String(int num,char *str) * details int转string * * param[in] num:待转换int str:指向转换得到字符串的指针 * param[out] * * return str:指向转换得到字符串的指针 * * note */ char* Int2String(int num,char *str)//10进制 { int i = 0;//指示填充str if(num<0)//如果num为负数,将num变正 { num = -num; str[i++] = '-'; } //转换 do { str[i++] = num%10+48;//取num最低位 字符0~9的ASCII码是48~57;简单来说数字0+48=48,ASCII码对应字符'0' num /= 10;//去掉最低位 }while(num);//num不为0继续循环 str[i] = '\0'; //确定开始调整的位置 int j = 0; if(str[0]=='-')//如果有负号,负号不用调整 { j = 1;//从第二位开始调整 ++i;//由于有负号,所以交换的对称轴也要后移1位 } //对称交换 for(;j<i/2;j++) { //对称交换两端的值 其实就是省下中间变量交换a+b的值:a=a+b;b=a-b;a=a-b; str[j] = str[j] + str[i-1-j]; str[i-1-j] = str[j] - str[i-1-j]; str[j] = str[j] - str[i-1-j]; } return str;//返回转换后的值 } /********************************************ubus相关函数*******************************************/ /* * fn static void weather_ubus_update_event_generate(int flag); * details 通过ubus send将更新得到的天气数据发送给其他相关模块 * * param[in] * param[out] * * return * * note */ static void weather_ubus_update_event_generate(int flag) { static struct blob_buf g_ubus_buf; void *table_len = NULL; time_t timep; struct tm date; blob_buf_init(&g_ubus_buf, 0); time(&timep); /* 获取当前unix时间 */ if(0 == flag) /* 0 == flag,发送当日实时天气数据 */ { date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "realtime"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature" , realtime_weather_info.temperature); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , realtime_weather_info.temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , realtime_weather_info.temperatureMax); blobmsg_add_string(&g_ubus_buf , "weather_type" , realtime_weather_info.weatherType); blobmsg_close_table(&g_ubus_buf, table_len); INFO("[weather_server]: Ubus send realtime weather, renew time:%ld", timep); } else if(1 == flag) /* 1 == flag,发送未来三天天气数据 */ { timep += 86400; /* 调整到后一天同一时刻 */ date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "tomorrow"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , forecast_weather_info[0].temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , forecast_weather_info[0].temperatureMax); blobmsg_add_string(&g_ubus_buf , "day_weather_type" , forecast_weather_info[0].dayWeatherType); blobmsg_add_string(&g_ubus_buf , "night_weather_type" , forecast_weather_info[0].nightWeatherType); blobmsg_close_table(&g_ubus_buf, table_len); timep += 86400; /* 调整到后一天同一时刻 */ date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "2_days_later"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , forecast_weather_info[1].temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , forecast_weather_info[1].temperatureMax); blobmsg_add_string(&g_ubus_buf , "day_weather_type" , forecast_weather_info[1].dayWeatherType); blobmsg_add_string(&g_ubus_buf , "night_weather_type" , forecast_weather_info[1].nightWeatherType); blobmsg_close_table(&g_ubus_buf, table_len); timep += 86400; /* 调整到后一天同一时刻 */ date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "3_days_later"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , forecast_weather_info[2].temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , forecast_weather_info[2].temperatureMax); blobmsg_add_string(&g_ubus_buf , "day_weather_type" , forecast_weather_info[2].dayWeatherType); blobmsg_add_string(&g_ubus_buf , "night_weather_type" , forecast_weather_info[2].nightWeatherType); blobmsg_close_table(&g_ubus_buf, table_len); INFO("[weather_server]: Ubus send forecast weather, renew time:%ld", timep - 86400 * 3); } else /* 2 == flag,发送小时级预报数据 */ { date = *(localtime(&timep)); table_len = blobmsg_open_table(&g_ubus_buf, "realtime"); blobmsg_add_u32(&g_ubus_buf , "month" , date.tm_mon + 1); blobmsg_add_u32(&g_ubus_buf , "day" , date.tm_mday); blobmsg_add_u32(&g_ubus_buf , "temperature" , realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].temperature); blobmsg_add_u32(&g_ubus_buf , "temperature_min" , realtime_weather_info.temperatureMin); blobmsg_add_u32(&g_ubus_buf , "temperature_max" , realtime_weather_info.temperatureMax); blobmsg_add_string(&g_ubus_buf , "weather_type" , realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].weatherType); blobmsg_close_table(&g_ubus_buf, table_len); INFO("[weather_server]: Ubus send realtime weather, renew time:%ld", timep); DEBUG("houridx:%d,temperature:%d,weather_type:%s",realtime_weather_info.houridx,realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].temperature, realtime_weather_info.forecast6Hours[realtime_weather_info.houridx].weatherType); } /* ubus send event */ ubus_send_event(ubus_ctx, "weather_info_update", g_ubus_buf.head); } /* 清除指定配置项 */ static void uci_del(struct uci_context *p_uci_ctx,const char *section, const char *option) { struct uci_ptr ptr; memset(&ptr, 0, sizeof(struct uci_ptr)); ptr.package = "weather"; ptr.section = section; ptr.option = option; uci_delete(p_uci_ctx, &ptr); return; } /* 清除天气数据 */ static void del_weather_info(void) { struct uci_context *uci_tmpctx = NULL; struct uci_ptr ptr; uci_tmpctx = uci_alloc_context(); if (!uci_tmpctx) { return; } ptr.package = "weather"; ptr.p = uci_lookup_package(uci_tmpctx, "weather"); uci_load(uci_tmpctx, "weather", &ptr.p); uci_del(uci_tmpctx,"realtime","temperature"); uci_del(uci_tmpctx,"realtime","temperatureMax"); uci_del(uci_tmpctx,"realtime","temperatureMin"); uci_del(uci_tmpctx,"realtime","weatherType"); uci_del(uci_tmpctx,"realtime","month"); uci_del(uci_tmpctx,"realtime","day"); uci_del(uci_tmpctx,"tomorrow","temperatureMax"); uci_del(uci_tmpctx,"tomorrow","temperatureMin"); uci_del(uci_tmpctx,"tomorrow","dayWeatherType"); uci_del(uci_tmpctx,"tomorrow","nightWeatherType"); uci_del(uci_tmpctx,"tomorrow","month"); uci_del(uci_tmpctx,"tomorrow","day"); uci_del(uci_tmpctx,"2_days_later","temperatureMax"); uci_del(uci_tmpctx,"2_days_later","temperatureMin"); uci_del(uci_tmpctx,"2_days_later","dayWeatherType"); uci_del(uci_tmpctx,"2_days_later","nightWeatherType"); uci_del(uci_tmpctx,"2_days_later","month"); uci_del(uci_tmpctx,"2_days_later","day"); uci_del(uci_tmpctx,"3_days_later","temperatureMax"); uci_del(uci_tmpctx,"3_days_later","temperatureMin"); uci_del(uci_tmpctx,"3_days_later","dayWeatherType"); uci_del(uci_tmpctx,"3_days_later","nightWeatherType"); uci_del(uci_tmpctx,"3_days_later","month"); uci_del(uci_tmpctx,"3_days_later","day"); uci_commit(uci_tmpctx, &ptr.p, false); uci_free_context(uci_tmpctx); return; } /* * fn static void ubus_collect_now(struct ubus_context *ubus_ctx, * struct ubus_event_handler *ev, * const char *type, struct blob_attr *msg); * details ubus对象方法回调函数,响应ubus send weather_settings_update,更新地理位置参数并立即更新天气信息 * * param[in] * param[out] * * return * * note */ static void ubus_collect_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg) { int status = 0; int temperature_unit = -1; uint32_t location_key = 0; struct blob_attr *tb[WEATHER_SETTINGS_MAX] = {NULL}; char buf[128] = {0}; status = blobmsg_parse(ubus_policy, WEATHER_SETTINGS_MAX, tb, blob_data(msg), blob_len(msg)); if (status < 0) { return; } if (tb[TEMPERATURE_UNIT] && blob_data(tb[TEMPERATURE_UNIT])) { temperature_unit = blobmsg_get_u32(tb[TEMPERATURE_UNIT]); } else { ERR("invalid temperature_unit"); } if (tb[LOCATION_KEY] && blob_data(tb[LOCATION_KEY])) { location_key = blobmsg_get_u32(tb[LOCATION_KEY]); } else { ERR("invalid location_key"); } if (tb[CITY_NAME] && blob_data(tb[CITY_NAME])) { snprintf(buf, sizeof(buf), "%s", blobmsg_get_string(tb[CITY_NAME])); } else { ERR("invalid city_name"); } INFO("[weather_server] Ubus rec: temperature_unit=%d, location_key=%d, city_name=%s",temperature_unit, location_key, buf); del_weather_info(); /* 更新天气信息 */ realtime_weather_info.houridx = 6; /* 小于6会导致不立即从云更新数据 */ weather_timer_cb(&timer); } /* 立即更新天气 */ static void ubus_update_now(struct ubus_context *ubus_ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg) { del_weather_info(); /* 更新天气信息 */ realtime_weather_info.houridx = 6; /* 小于6会导致不立即从云更新数据 */ weather_timer_cb(&timer); } /* * fn static void ubus_reconn_timer(struct uloop_timeout *timeout) * details ubus重连 * * param[in] * param[out] * * return * * note */ static void ubus_reconn_timer(struct uloop_timeout *timeout) { static struct uloop_timeout retry = { .cb = ubus_reconn_timer, }; DEBUG("S:ubus_connection_lost"); if (ubus_reconnect(ubus_ctx, ubus_patch) != 0) { /* 设置每过两秒尝试重连ubusd */ uloop_timeout_set(&retry, 2000); return; } ubus_add_uloop(ubus_ctx); } /* * fn static int weather_ubus_init(char *path) * details ubus初始化 * * param[in] * param[out] * * return * * note */ static int weather_ubus_init(char *path) { ubus_patch = path; /* 连接ubusd */ ubus_ctx = ubus_connect(path); if (!ubus_ctx) { ERR("S:Failed to connect ubusd"); return -1; } /* 设置断线重连回调函数为ubus_reconn_timer */ ubus_ctx->connection_lost = (void (*)(struct ubus_context *))ubus_reconn_timer; DEBUG("S:succeed to connect ubusd"); if (ubus_register_event_handler(ubus_ctx, &weather_settings_ubus_notify, "weather_settings_update") != 0) { ERR("S:Failed to add object to ubusd"); return -1; } if (ubus_register_event_handler(ubus_ctx, &weather_update_ubus_notify, "weather_update") != 0) { ERR("S:Failed to add object to ubusd"); return -1; } /* 向uloop注册 */ ubus_add_uloop(ubus_ctx); DEBUG("S:succeed to add object to ubusd"); return 0; } /* * fn static int weather_ubus_deinit(void) * details 释放ubus变量 * * param[in] * param[out] * * return * * note */ static int weather_ubus_deinit(void) { ubus_unregister_event_handler(ubus_ctx, &weather_settings_ubus_notify); ubus_unregister_event_handler(ubus_ctx, &weather_update_ubus_notify); if(ubus_ctx) { ubus_free(ubus_ctx); } return 0; } /**********************************************天气信息请求*****************************************/ /* * fn static size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid) * details 将从云端收到的数据写入复制到指定字符串中 * * param[in] * param[out] * * return * * note */ static size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid) { unsigned int len = (unsigned int)size * (unsigned int)nmemb; char *str = malloc(len + 1); if (NULL == str || NULL == buffer) { return -1; } char* pData = buffer; memset(str, 0, len + 1); memcpy(str, pData, len); DEBUG("response: %s", str); char **response = lpVoid; *response = str; return len; } /* * fn static size_t cloud_https_post(const char *pUrl, const char *requestHeader, * const char *request, char **response, st_http_resinfo *pHttpResInfo) * details 发送post请求,从云端获取天气数据 * * param[in] * param[out] * * return * * note */ static size_t cloud_https_post(const char *pUrl, const char *requestHeader, const char *request, char **response, st_http_resinfo *pHttpResInfo) { CURLcode res; CURL* curl = NULL; struct curl_slist *headers = NULL; if (NULL == pUrl || NULL == request || NULL == response || NULL == pHttpResInfo) { return CURLE_FAILED_INIT; } DEBUG("pUrl:%s requestHeader:%s request:%s", pUrl, requestHeader, request); res = curl_global_init(CURL_GLOBAL_ALL); if (CURLE_OK != res) { ERR("curl global init fail and ret %d", res); return res; } curl = curl_easy_init(); if (NULL == curl) { res = CURLE_FAILED_INIT; ERR("curl init fail"); goto exit; } // headers = curl_slist_append(headers, "Content-Type: application/json;charset=UTF-8"); headers = curl_slist_append(headers, "Content-Type: application/json"); if (NULL == headers) { ERR("curl get header list fail"); goto exit; } if ((NULL != requestHeader) && (0 < strlen(requestHeader))) { DEBUG("requestHeader is %s", requestHeader); headers = curl_slist_append(headers, requestHeader); if (NULL == headers) { ERR("curl append requestHeader fail"); goto exit; } } //set url // DEBUG("request_url:%s",pUrl); res = curl_easy_setopt(curl, CURLOPT_URL, pUrl); if (CURLE_OK != res) { ERR("curl set option CURLOPT_URL ret %d", res); goto exit; } //set header //DEBUG("request_header:%s",headers); res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); if (CURLE_OK != res) { ERR("curl set option CURLOPT_HTTPHEADER ret %d", res); goto exit; } //set post method res = curl_easy_setopt(curl, CURLOPT_POST, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_POST ret %d", res); goto exit; } // DEBUG("request_data:%s",request); res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request); if (CURLE_OK != res) { ERR("curl set option CURLOPT_POSTFIELDS ret %d", res); goto exit; } //set read/write params res = curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); if (CURLE_OK != res) { ERR("curl set option CURLOPT_READFUNCTION ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post); if (CURLE_OK != res) { ERR("curl set option CURLOPT_WRITEFUNCTION ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response); if (CURLE_OK != res) { ERR("curl set option CURLOPT_WRITEDATA ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_NOSIGNAL ret %d", res); goto exit; } //set certificate info res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_SSL_VERIFYPEER ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_CAINFO, CA_CRT_PATH); if (CURLE_OK != res) { ERR("curl set option CURLOPT_CAINFO ret %d", res); goto exit; } //set CURLOPT_CONNECTTIMEOUT res = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, POST_TRANSFER_TIMEOUT); if (CURLE_OK != res) { ERR("curl set option CURLOPT_CONNECTTIMEOUT ret %d", res); goto exit; } //set CURLOPT_TIMEOUT res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, POST_CONNECT_TIMEOUT); if (CURLE_OK != res) { ERR("curl set option CURLOPT_TIMEOUT ret %d", res); goto exit; } //CURLOPT needs to be set_ FOLLOWLOCATION is 1, otherwise, the data after redirecting will not be returned res = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); if (CURLE_OK != res) { ERR("curl set option CURLOPT_FOLLOWLOCATION ret %d", res); goto exit; } res = curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); if (CURLE_OK != res) { ERR("curl set option CURL_SSLVERSION_TLSv1_2 ret %d", res); goto exit; } res = curl_easy_perform(curl); curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &(pHttpResInfo->status_code)); DEBUG("cloud_https_post done. ret %d, http status code %d", res, pHttpResInfo->status_code); exit: if (headers) { curl_slist_free_all(headers); } if (curl) { curl_easy_cleanup(curl); } curl_global_cleanup(); return res; } /* * fn int get_token_url(char *token, char *url) * details 获取device token和云端天气预报请求url * * param[in] * param[out] * * return * * note */ int get_token_url(char *token, char *url) { int ret = -1; int retry_count = 3; FILE *fp = NULL; while (retry_count > 0) { if((fp = fopen(FILE_CLOUD_TOKEN_WEATHER, "r"))) { fscanf(fp, "%s", token); fscanf(fp, "%s", url); fclose(fp); ret = 0; break; } else { system("cloud_getDevToken weather"); } retry_count--; } return ret; } /* * fn static int set_weather_cloud_request_data(char *device_token, char *request_data) * details 读取uci配置中的location_key,与输入参数device_token共同构造post请求参数 * * param[in] char *device_token 从云端获取的device token * char *request_data 存储post请求参数字符串 * param[out] * * return * * note */ static int set_weather_cloud_request_data(char *device_token, char *request_data) { //int ret = -1; json_object* request_data_json = NULL; const char* request_data_out = NULL; //FILE *fp = NULL; int locationkey = 0; locationkey = uci_get_locationkey(); if ( -1 == locationkey) { ERR("uci_get_locationkey failed"); return -1; } if ((request_data_json = json_object_new_object()) == NULL) { return -1; } json_object_object_add(request_data_json, "locationKey", json_object_new_int(locationkey)); json_object_object_add(request_data_json, "deviceToken", json_object_new_string(device_token)); request_data_out = json_object_to_json_string(request_data_json); memcpy(request_data, request_data_out, strlen(request_data_out)); if (request_data_json) { json_object_put(request_data_json); } return 0; } /* * fn int get_realtime_info_from_cloud(struct realtime_weather_info_struct *realtime_weather_info, * char *device_token, char *url_prefix) * details 从云端获取当日天气数据并解析 * * param[in] struct realtime_weather_info_struct *realtime_weather_info 存储当日天气数据结构体 * char *device_token 从云端获取的device token * char *url_prefix 云端请求天气数据url前缀 * param[out] * * return ret 0表示获取数据成功,-1表示失败 * * note */ int get_realtime_info_from_cloud(struct realtime_weather_info_struct *realtime_weather_info, char *device_token, char *url_prefix) { int ret = -1; int i = 0; char request_url[128] = {0}; char request_header[64] = {0}; char tmpstr[40] = {0}; char request_data[512] = {0}; char *response = ""; st_http_resinfo httpResInfo; json_object* response_json = NULL; json_object* errorcode = NULL; json_object* message = NULL; json_object* result = NULL; json_object* temperature = NULL; json_object* temperatureMax = NULL; json_object* temperatureMin = NULL; json_object* weatherType = NULL; json_object* forecast6Hours = NULL; json_object* hourlyForecats = NULL; int errorcode_data = -1; const char* message_data = NULL; int temperature_data = -1; int temperatureMax_data = -1; int temperatureMin_data = -1; int hourlyTemperature_data[6] = {0}; const char* weatherType_data = NULL; const char* hourlyWeatherType_data[6] = {NULL}; if (realtime_weather_info == NULL || device_token == NULL || url_prefix == NULL) { ERR("params error"); ret = -1; goto exit; } memset(&httpResInfo, 0, sizeof(st_http_resinfo)); sprintf(request_url, "%s%s", url_prefix, REALTIME_URL_POSTFIX); if (-1 == set_weather_cloud_request_data(device_token, request_data)) { ERR("set_weather_cloud_request_data error"); ret = -1; goto exit; } //get post result cloud_https_post(request_url, request_header, request_data, &response, &httpResInfo); DEBUG("httpResInfo.status_code:%ld",httpResInfo.status_code); DEBUG("response:%s",response); if (response && httpResInfo.status_code == 200) { response_json = json_tokener_parse(response); errorcode = json_object_object_get(response_json, "code"); errorcode_data = json_object_get_int(errorcode); if (0 != errorcode_data) { weather_errorcode = errorcode_data; sprintf(tmpstr, "get weather info errorcode:%d", errorcode_data); // uci_set_option("global", "error", tmpstr); ret = -1; goto exit; } message = json_object_object_get(response_json, "message"); result = json_object_object_get(response_json, "result"); temperature = json_object_object_get(result, "temperature"); temperatureMax = json_object_object_get(result, "temperatureMax"); temperatureMin = json_object_object_get(result, "temperatureMin"); weatherType = json_object_object_get(result, "weatherType"); message_data = json_object_get_string(message); temperature_data = json_object_get_int(temperature); temperatureMax_data = json_object_get_int(temperatureMax); temperatureMin_data = json_object_get_int(temperatureMin); weatherType_data = json_object_get_string(weatherType); forecast6Hours = json_object_object_get(result, "forecast6Hours"); if ( json_type_array != json_object_get_type(forecast6Hours) || 6 != json_object_array_length(forecast6Hours) ) { ret = -1; goto exit; } for ( i = 0; i < 6; i++) { hourlyForecats = json_object_array_get_idx(forecast6Hours, i); temperature = json_object_object_get(hourlyForecats, "temperature"); weatherType = json_object_object_get(hourlyForecats, "weatherType"); hourlyTemperature_data[i] = json_object_get_int(temperature); hourlyWeatherType_data[i] = json_object_get_string(weatherType); } if (0 == errorcode_data && message_data && weatherType_data) { DEBUG("errorcode : %d", errorcode_data); DEBUG("message : %s", message_data); DEBUG("temperature : %d", temperature_data); DEBUG("temperatureMax : %d", temperatureMax_data); DEBUG("temperatureMin : %d", temperatureMin_data); DEBUG("weatherType : %s", weatherType_data); // tmpstr = uci_get_unit(); // DEBUG("unit:%s",tmpstr); if (0 == strcmp(uci_get_unit(),"centigrade")) { realtime_weather_info->temperature = (temperature_data - 32) / 1.8; realtime_weather_info->temperatureMax = (temperatureMax_data -32) / 1.8; realtime_weather_info->temperatureMin = (temperatureMin_data - 32) / 1.8; for ( i = 0; i < 6; i++) { realtime_weather_info->forecast6Hours[i].temperature = (hourlyTemperature_data[i] - 32) / 1.8; DEBUG("%d:temperature:%d\n",i,realtime_weather_info->forecast6Hours[i].temperature); } } else { realtime_weather_info->temperature = temperature_data; realtime_weather_info->temperatureMax = temperatureMax_data; realtime_weather_info->temperatureMin = temperatureMin_data; for ( i = 0; i < 6; i++) { realtime_weather_info->forecast6Hours[i].temperature = hourlyTemperature_data[i]; DEBUG("%d:temperature:%d\n",i,realtime_weather_info->forecast6Hours[i].temperature); } } sprintf(realtime_weather_info->weatherType, "%s", weatherType_data); for ( i = 0; i < 6; i++) { sprintf(realtime_weather_info->forecast6Hours[i].weatherType, "%s", hourlyWeatherType_data[i]); DEBUG("%d:weatherType:%s\n",i,realtime_weather_info->forecast6Hours[i].weatherType); } weather_errorcode = errorcode_data; memcpy(weather_message, message_data, strlen(message_data)); ret = 0; } } else { // uci_set_option("global", "error", "cloud_https_post failed"); ret = -1; } exit: if (response_json) { json_object_put(response_json); } if (errorcode) { json_object_put(errorcode); } if (message) { json_object_put(message); } if (result) { json_object_put(result); } if (temperature) { json_object_put(temperature); } if (temperatureMax) { json_object_put(temperatureMax); } if (temperatureMin) { json_object_put(temperatureMin); } if (weatherType) { json_object_put(weatherType); } if (forecast6Hours) { json_object_put(forecast6Hours); } if (hourlyForecats) { json_object_put(hourlyForecats); } return ret; } /* * fn int get_forecast_info_from_cloud(struct forecast_weather_info_struct *forecast_weather_info, * char *device_token, char *url_prefix) * details 从云端获取未来三天天气数据并解析 * * param[in] struct forecast_weather_info_struct *forecast_weather_info 存储未来三天天气数据结构体 * char *device_token 从云端获取的device token * char *url_prefix 云端请求天气数据url前缀 * param[out] * * return ret 0表示获取数据成功,-1表示失败 * * note */ int get_forecast_info_from_cloud(struct forecast_weather_info_struct *forecast_weather_info, char *device_token, char *url_prefix) { int ret = -1; // int ret_post = 0; int i = 0; char request_url[128] = {0}; char request_header[64] = {0}; char tmpstr[40] = {0}; char request_data[512] = {0}; char *response = NULL; st_http_resinfo httpResInfo; json_object* response_json = NULL; json_object* errorcode = NULL; json_object* message = NULL; json_object* result = NULL; json_object* forecastList = NULL; json_object* ListItem = NULL; json_object* temperatureMax = NULL; json_object* temperatureMin = NULL; json_object* dayWeatherType = NULL; json_object* nightWeatherType = NULL; int errorcode_data = -1; const char* message_data = NULL; int temperatureMax_data = -1; int temperatureMin_data = -1; const char* dayWeatherType_data = NULL; const char* nightWeatherType_data = NULL; if (forecast_weather_info == NULL || device_token == NULL || url_prefix == NULL) { ERR("params error"); ret = -1; goto exit; } memset(&httpResInfo, 0, sizeof(st_http_resinfo)); sprintf(request_url, "%s%s", url_prefix, FORECASTS_URL_POSTFIX); if (-1 == set_weather_cloud_request_data(device_token, request_data)) { ERR("set_weather_cloud_request_data error"); ret = -1; goto exit; } //get post result cloud_https_post(request_url, request_header, request_data, &response, &httpResInfo); DEBUG("httpResInfo.status_code:%ld",httpResInfo.status_code); DEBUG("response:%s",response); if (response && httpResInfo.status_code == 200) { response_json = json_tokener_parse(response); errorcode = json_object_object_get(response_json, "code"); errorcode_data = json_object_get_int(errorcode); if (0 != errorcode_data) { weather_errorcode = errorcode_data; sprintf(tmpstr, "get weather info errorcode:%d", errorcode_data); // uci_set_option("global", "error", tmpstr); ret = -1; goto exit; } message = json_object_object_get(response_json, "message"); result = json_object_object_get(response_json, "result"); forecastList = json_object_object_get(result, "forecastList"); message_data = json_object_get_string(message); if (0 == errorcode_data && message_data) { DEBUG("errorcode : %d", errorcode_data); DEBUG("message : %s", message_data); for ( i = 0; i < 3; i++) { ListItem = json_object_array_get_idx(forecastList,i); temperatureMax = json_object_object_get(ListItem, "temperatureMax"); temperatureMin = json_object_object_get(ListItem, "temperatureMin"); dayWeatherType = json_object_object_get(ListItem, "dayWeatherType"); nightWeatherType = json_object_object_get(ListItem, "nightWeatherType"); temperatureMax_data = json_object_get_int(temperatureMax); temperatureMin_data = json_object_get_int(temperatureMin); dayWeatherType_data = json_object_get_string(dayWeatherType); nightWeatherType_data = json_object_get_string(nightWeatherType); DEBUG("temperatureMax : %d", temperatureMax_data); DEBUG("temperatureMin : %d", temperatureMin_data); DEBUG("dayWeatherType : %s", dayWeatherType_data); DEBUG("nightWeatherType : %s", nightWeatherType_data); if (dayWeatherType_data && nightWeatherType_data) { // tmpstr = uci_get_unit(); // DEBUG("unit:%s",tmpstr); if (0 == strcmp(uci_get_unit(),"centigrade")) { forecast_weather_info[i].temperatureMax = (temperatureMax_data - 32) / 1.8; forecast_weather_info[i].temperatureMin = (temperatureMin_data - 32) / 1.8; } else { forecast_weather_info[i].temperatureMax = temperatureMax_data; forecast_weather_info[i].temperatureMin = temperatureMin_data; } sprintf(forecast_weather_info[i].dayWeatherType, "%s", dayWeatherType_data); sprintf(forecast_weather_info[i].nightWeatherType, "%s", nightWeatherType_data); } } weather_errorcode = errorcode_data; memcpy(weather_message, message_data, strlen(message_data)); ret = 0; } } else { // uci_set_option("global", "error", "cloud_https_post failed"); ret = -1; } exit: if (response_json) { json_object_put(response_json); } if (errorcode) { json_object_put(errorcode); } if (message) { json_object_put(message); } if (result) { json_object_put(result); } if (forecastList) { json_object_put(forecastList); } if (ListItem) { json_object_put(ListItem); } if (temperatureMax) { json_object_put(temperatureMax); } if (temperatureMin) { json_object_put(temperatureMin); } if (dayWeatherType) { json_object_put(dayWeatherType); } if (nightWeatherType) { json_object_put(nightWeatherType); } return ret; } /* * fn static int update_weather_url(void) * details 更新天气数据 * * param[in] * param[out] * * return 0表示获取数据成功,-1表示失败 * * note */ static int update_weather_url(void) { char device_token[MAX_TOKEN_LEN] = {0}; char cloud_weather_url[MAX_URL_LEN] = {0}; int i = 0; /* init */ realtime_weather_info.temperature = 0; realtime_weather_info.temperatureMax = 0; realtime_weather_info.temperatureMin = 0; memset(realtime_weather_info.weatherType, 0, sizeof(realtime_weather_info.weatherType)); for ( i = 0; i < 6; i++) { realtime_weather_info.forecast6Hours[i].temperature = 0; // realtime_weather_info.forecast6Hours[i].datetime = 0; memset(realtime_weather_info.forecast6Hours[i].weatherType, 0, sizeof(realtime_weather_info.weatherType)); } for ( i = 0; i < 3; i++) { forecast_weather_info[i].temperatureMax = 0; forecast_weather_info[i].temperatureMin = 0; memset(forecast_weather_info[i].dayWeatherType, 0, sizeof(forecast_weather_info[i].dayWeatherType)); memset(forecast_weather_info[i].nightWeatherType, 0, sizeof(forecast_weather_info[i].nightWeatherType)); } /* online request */ if (0 == (get_token_url(device_token, cloud_weather_url))) { /* get_realtime_info_from_cloud */ if (0 == get_realtime_info_from_cloud(&realtime_weather_info, device_token, cloud_weather_url)) { weather_ubus_update_event_generate(0); if (1 != uci_renew(0)) { ERR("set_realtime_info_to_uci fail"); // uci_set_option("global", "error", "set_realtime_info_to_uci fail"); return -1; } realtime_weather_info.houridx = 0; /* 重置当前小时数 */ DEBUG("get_realtime_info_from_cloud succeed"); } else { WARNING("get_realtime_info_from_cloud error"); return -1; } /* get_forecast_info_from_cloud */ if (0 == get_forecast_info_from_cloud(forecast_weather_info, device_token, cloud_weather_url)) { weather_ubus_update_event_generate(1); if (1 != uci_renew(1)) { ERR("set_forecast_info_to_uci fail"); // uci_set_option("global", "error", "set_forecast_info_to_uci fail"); return -1; } DEBUG("get_forecast_info_from_cloud succeed"); } else { WARNING("get_forecast_info_from_cloud error"); return -1; } } else { ERR("get_token_url error"); return -1; } return 0; } /**********************************************uci相关函数******************************************/ /* * fn static void config_free(void) * details uci变量释放 * * param[in] * param[out] * * return * * note */ static void config_free(void) { if (uci_weather) { uci_unload(uci_ctx, uci_weather); uci_weather = NULL; } if (uci_ctx) { uci_free_context(uci_ctx); uci_ctx = NULL; } } /* * fn static struct uci_package *config_init_package(char *config) * details 获取uci文件package * * param[in] * param[out] * * return * * note */ static struct uci_package *config_init_package(char *config) { struct uci_package *p = NULL; if (!uci_ctx) { /* 申请uci上下文结构uci_ctx */ uci_ctx = uci_alloc_context(); // uci_ctx->flags &= ~UCI_FLAG_STRICT; } else { /* 查找config文件 */ p = uci_lookup_package(uci_ctx, config); if (p) { uci_unload(uci_ctx, p); } DEBUG("S:uci_unload"); } /* 加载配置到内存 */ if ( UCI_OK != uci_load(uci_ctx, config, &p) ) { p = NULL; DEBUG("S:uci load error"); } return p; } /* * fn static int config_alloc(void) * details 获取uci文件package,地址保存到全局变量uci_weather中 * * param[in] * param[out] * * return * * note */ static int config_alloc(void) { uci_weather = config_init_package("weather"); if (!uci_weather) { ERR("S:Failed to load weather config"); return 0; } DEBUG("S:succeed to load weather config"); return 1; } /* * fn static int uci_init(void) * details uci初始化 * * param[in] * param[out] * * return * * note */ static int uci_init(void) { struct uci_section *tmp_sec; /* 获取uci配置文件 */ if( !config_alloc()) { ERR("S:config_alloc error"); config_free(); return 0; } /* 检查uci配置文件中的section */ tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "global"); if ( !tmp_sec) { ERR("S:lookup global section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "realtime"); if ( !tmp_sec) { ERR("S:lookup realtime section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "forecast"); if ( !tmp_sec) { ERR("S:lookup forecast section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "tomorrow"); if ( !tmp_sec) { ERR("S:lookup forecast1 section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "2_days_later"); if ( !tmp_sec) { ERR("S:lookup forecast2 section failed"); config_free(); return 0; } tmp_sec = uci_lookup_section(uci_ctx, uci_weather, "3_days_later"); if ( !tmp_sec) { ERR("S:lookup forecast3 section failed"); config_free(); return 0; } return 1; } /* * fn static int uci_set_option(char *uci_section, char *uci_option, char *uci_value) * details 配置uci配置文件option * * param[in] char *uci_section section名 * char *uci_option option的key, * char *uci_value option的value * param[out] * * return * * note */ static int uci_set_option(char *uci_section, char *uci_option, char *uci_value) { int ret = 0; struct uci_ptr ptr ={ .package = "weather", .section = uci_section, .option = uci_option, .value = uci_value }; /* 配置uci配置文件option,key=uci_option,value=uci_value*/ ret = uci_set(uci_ctx, &ptr); if( UCI_OK != ret) { ERR("S:set %s failed",uci_option); return 0; } // DEBUG("S:set %s ok",uci_option); /* 保存配置 */ uci_save(uci_ctx, ptr.p); uci_commit(uci_ctx, &ptr.p, false); return 1; } /* * fn int uci_get_locationkey(void) * details 从uci配置文件中读取locationkey * * param[in] * param[out] * * return key 从uci配置文件中读取的locationkey * * note */ int uci_get_locationkey(void) { int key = 0; const char *key_str = NULL; struct uci_context *tmpCtx = NULL; struct uci_package *tmppkg = NULL; struct uci_section *tmpsec = NULL; tmpCtx = uci_alloc_context(); if ( UCI_OK != uci_load(tmpCtx, "weather", &tmppkg) ) { // uci_set_option("global", "error", "uci_load weather error"); ERR("S:uci load error"); key = -1; goto exit; } tmpsec = uci_lookup_section(tmpCtx, tmppkg, "global"); if ( !tmpsec) { // uci_set_option("global", "error", "lookup global section failed"); ERR("S:lookup global section failed"); key = -1; goto exit; } key_str = uci_lookup_option_string(tmpCtx, tmpsec, "location_key"); if(!key_str) { // uci_set_option("global", "error", "lookup location_key option failed"); ERR("S:lookup location_key option failed"); key = -1; goto exit; } key = atoi(key_str); DEBUG("uci_get_option location_key:%d",key); exit: uci_unload(tmpCtx, tmppkg); uci_free_context(tmpCtx); return key; } /* * fn const char *uci_get_unit(void) * details 从uci配置文件中读取temperature_unit * * param[in] * param[out] * * return unit_str 从uci配置文件中读取的temperature_unit * * note */ const char *uci_get_unit(void) { const char *unit_str = NULL; struct uci_context *tmpCtx = NULL; struct uci_package *tmppkg = NULL; struct uci_section *tmpsec = NULL; tmpCtx = uci_alloc_context(); if ( UCI_OK != uci_load(tmpCtx, "weather", &tmppkg) ) { // uci_set_option("global", "error", "uci_load weather error"); ERR("S:uci load error"); goto exit; } tmpsec = uci_lookup_section(tmpCtx, tmppkg, "global"); if ( !tmpsec) { // uci_set_option("global", "error", "lookup global section failed"); ERR("S:lookup global section failed"); goto exit; } unit_str = uci_lookup_option_string(tmpCtx, tmpsec, "temperature_unit"); if(!unit_str) { // uci_set_option("global", "error", "lookup unit option failed"); unit_str = "fahrenheit"; /* 如果配置缺失,默认华氏度 */ ERR("S:lookup unit option failed"); goto exit; } exit: uci_unload(tmpCtx, tmppkg); uci_free_context(tmpCtx); return unit_str; } /* * fn static void uci_renew(int flag) * details 将从云端拿到的天气数据写入uci配置文件, * * param[in] int flag 为0时表示写入当日天气数据,为1时表示写入未来三天天气数据 * param[out] * * return 0表示写入失败,1表示写入成功 * * note */ static int uci_renew(int flag) { time_t timep; struct tm date; // char time_cu[10] = ""; char section[20] = ""; char tmpstr[20] = ""; int i = 0; /* 获取当前unix时间 */ time(&timep); /* 配置uci配置文件对应option */ if (0 == flag) { /* 更新实时天气信息 */ date = * (localtime(&timep)); if (1 != uci_set_option("realtime", "errorcode", Int2String(weather_errorcode,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "message", weather_message)) { return 0; } if (1 != uci_set_option("realtime", "time_renew", Int2String((int)timep,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "month", Int2String(date.tm_mon + 1,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "day", Int2String(date.tm_mday,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "temperature", Int2String(realtime_weather_info.temperature,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "temperatureMax", Int2String(realtime_weather_info.temperatureMax,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "temperatureMin", Int2String(realtime_weather_info.temperatureMin,tmpstr))) { return 0; } if (1 != uci_set_option("realtime", "weatherType", realtime_weather_info.weatherType)) { return 0; } DEBUG("S:realtime weather uci renew time:%ld", timep); } else { /* 更新预报天气信息 */ if (1 != uci_set_option("forecast", "errorcode", Int2String(weather_errorcode,tmpstr))) { return 0; } if (1 != uci_set_option("forecast", "message", weather_message)) { return 0; } if (1 != uci_set_option("forecast", "time_renew", Int2String((int)timep,tmpstr))) { return 0; } for (i = 0; i < 3; i++) { timep += 86400; /* 调整到后一天同一时刻 */ date = * (localtime(&timep)); if (0 == i) { sprintf(section,"tomorrow"); } else { sprintf(section,"%d_days_later",i + 1); } if (1 != uci_set_option(section, "temperatureMax", Int2String(forecast_weather_info[i].temperatureMax,tmpstr))) { return 0; } if (1 != uci_set_option(section, "temperatureMin", Int2String(forecast_weather_info[i].temperatureMin,tmpstr))) { return 0; } if (1 != uci_set_option(section, "dayWeatherType", forecast_weather_info[i].dayWeatherType)) { return 0; } if (1 != uci_set_option(section, "nightWeatherType", forecast_weather_info[i].nightWeatherType)) { return 0; } if (1 != uci_set_option(section, "month", Int2String(date.tm_mon + 1,tmpstr))) { return 0; } if (1 != uci_set_option(section, "day", Int2String(date.tm_mday,tmpstr))) { return 0; } } DEBUG("S:forecast weather uci renew time:%ld", timep - 86400 * 3); } return 1; } /**********************************************定时控制函数*****************************************/ /* * fn static void weather_timer_cb(struct uloop_timeout *timer) * details 定时更新天气数据,renew_interval控制下次更新时间间隔 * * param[in] * param[out] * * return * * note */ static void weather_timer_cb(struct uloop_timeout *timer) { if ( 6 <= realtime_weather_info.houridx ) { if (HOURLY_UPDATE_INTERVAL == renew_interval) { renew_interval = DEFAULT_INTERVAL; /* 兼容原有逻辑,否则更新失败时renew_interval=2h */ } if (0 != update_weather_url()) { ERR("S:update_weather_url failed"); if (DEFAULT_INTERVAL == renew_interval) { if (-20652 == weather_errorcode) { system("rm /tmp/cloud/cloud_token_weather"); /* devicetoken失效 */ renew_interval = FAST_INTERVAL; /* 10s后重试 */ } else { renew_interval = MID_INTERVAL; /* 5min后重试 */ } } else if(DEFAULT_INTERVAL > renew_interval * 2) { renew_interval *= 2; /* 重试时间*2 */ } else { renew_interval = DEFAULT_INTERVAL + 1; /* 最高时间间隔6h+1s,多1s防止误判,否则再次失败renew_interval又会缩短 */ } } else { // renew_interval = DEFAULT_INTERVAL; /* 成功后时间恢复6h */ renew_interval = HOURLY_UPDATE_INTERVAL; /* 成功后开始每小时更新 */ } } else { weather_ubus_update_event_generate(2); realtime_weather_info.houridx++; renew_interval = HOURLY_UPDATE_INTERVAL; /* 1h后刷新数据 */ } DEBUG("Period CallBack"); uloop_timeout_set(timer, renew_interval * 1000); } /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ /**************************************************************************************************/ /* GLOBAL_FUNCTIONS */ /**************************************************************************************************/ int main() { char *ubus_socket = NULL; // unsigned int seed; /* 随机种子 */ // int fd = -1; char buf[20] = ""; FILE *fp = NULL; realtime_weather_info.houridx = 6; /* 如果小于6会导致模块刚启动时不更新天气 */ memset(&timer, 0, sizeof(timer)); /* ubus初始化 */ uloop_init(); if (-1 == weather_ubus_init(ubus_socket)) { ERR("S:weather_ubus_init failed"); } /* uci初始化 */ if (0 == uci_init()) { ERR("S:uci_init failed"); } /* 通过ntp检查网络状态,后续断网导致的更新失败由原有的重试机制处理 */ while(1) { if ( (fp = fopen("/tmp/state/systime", "r") ) != NULL) { fgets(buf, 20, fp); fgets(buf, 20, fp); /* 连续读取两次以获取文件第二行内容 */ if ( 49 == buf[18] ) /* 如果systime.core.sync=1 */ { fclose(fp); break; } else { ERR("weather detect ntp not sync\n"); } fclose(fp); } sleep(10); } /* 配置定时更新函数 */ timer.cb = weather_timer_cb; uloop_timeout_set(&timer, 0); /* uloop启动 */ DEBUG("S:uloop_run start"); uloop_run(); DEBUG("S:uloop_run end"); /*uci变量释放*/ config_free(); /* curl释放*/ curl_global_cleanup(); /* ubus释放*/ weather_ubus_deinit(); uloop_done(); DEBUG("S:uloop_done"); return 0; }
12-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值