Invalid default value for 'lastUpdateTime'

本文解决了一个关于数据库字段设置的问题,具体为lastUpdateTime字段使用timestamp类型时,默认值设置为CURRENT_TIMESTAMP来避免错误。

错误:Invalid default value for 'lastUpdateTime'

错误:执行建表语句时,字段lastUpdateTime timestamp  not null  comment报错.

修改:lastUpdateTime     timestamp  not null  default CURRENT_TIMESTAMP  comment

 

/*************************************************************************************************/ /* INCLUDE_FILES */ /*************************************************************************************************/ #include "weather_service.h" /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ #define ME "weather" #define WEATHER_OBJ_PATH "X_TP_Weather" #define MAX_URL_LEN 256 #define MAX_RESPONSE_SIZE 4096 #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" /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ typedef struct { int temperature; int temperatureMax; int temperatureMin; int houridx; char weatherType[10]; struct { int temperature; char weatherType[10]; } forecast6Hours[6]; } realtime_weather_info_struct; typedef struct { int temperatureMax; int temperatureMin; char dayWeatherType[10]; char nightWeatherType[10]; } forecast_weather_info_struct; /*************************************************************************************************/ /* EXTERN_PROTOTYPES */ /*************************************************************************************************/ /*************************************************************************************************/ /* LOCAL_PROTOTYPES */ /*************************************************************************************************/ /*************************************************************************************************/ /* VARIABLES */ /*************************************************************************************************/ static amxd_dm_t *g_pdm = NULL; static amxo_parser_t *g_pparser = NULL; static uloop_timeout g_timer = { .cb = NULL }; realtime_weather_info_struct g_realtime_weather; forecast_weather_info_struct g_forecast_weather[3]; int g_errorcode = 0; char g_errormsg[20] = ""; /*************************************************************************************************/ /* LOCAL_FUNCTIONS */ /*************************************************************************************************/ const char* get_temperature_unit() { static const char* default_unit = "fahrenheit"; amxd_object_t *pobj_weather = NULL; amxd_object_t *pobj_config = NULL; pobj_weather = amxd_dm_findf(g_pdm, "X_TP_Weather"); if (!pobj_weather) { SAH_TRACEZ_WARN(ME, "Failed to find X_TP_Weather object."); return default_unit; } pobj_config = amxd_object_get_child(pobj_weather, "Config"); if (!pobj_config) { SAH_TRACEZ_WARN(ME, "Failed to find X_TP_Weather.Config."); return default_unit; } amxc_var_t unit_var; amxc_var_init(&unit_var); if (amxd_object_get_value(pobj_config, "TemperatureUnit", &unit_var) != 0) { SAH_TRACEZ_WARN(ME, "Failed to read TemperatureUnit from config."); amxc_var_clean(&unit_var); return default_unit; } const char* unit = amxc_var_string(&unit_var); if (!unit || (strcmp(unit, "centigrade") != 0 && strcmp(unit, "fahrenheit") != 0)) { SAH_TRACEZ_WARN(ME, "Invalid temperature unit value: %s. Using default.", unit ? unit : "NULL"); amxc_var_clean(&unit_var); return default_unit; } amxc_var_clean(&unit_var); return unit; } int fahrenheit_to_celsius(int f) { return (f - 32) * 5 / 9; } int get_token_url(char *token, char *url) { int ret = -1; int retry_count = 3; amxc_var_t args; amxc_var_t rets; FILE *fp = NULL; amxc_var_init(&args); amxc_var_init(&rets); 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 { amxc_var_set_type(&args, AMXC_VAR_ID_HTABLE); amxc_var_set_type(&rets, AMXC_VAR_ID_HTABLE); amxc_var_add_key(cstring_t, &args, "servicetype", SERVICE_TYPE); amxc_var_add_key(uint32_t, &args, "retrycount", 3); ret = amxb_call(amxb_be_who_has(CLOUD_PATH), CLOUD_HTTPS_PATH, GET_DEVICETOKEN_FUNC, &args, &rets, 5); if (ret != 0) { SAH_TRACEZ_ERROR("cloud", "get device token failed! error_code=%u", GETP_UINT32(&rets, "0.error_code")); goto exit; } } retry_count--; } exit: amxc_var_clean(&args); amxc_var_clean(&rets); return ret; } 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; } int get_location_key() { amxd_object_t *pobj_weather = amxd_dm_findf(g_pdm, "X_TP_Weather"); if (!pobj_weather) { SAH_TRACEZ_WARN(ME, "Failed to find X_TP_Weather object."); return -1; } amxc_var_t locationkey_var; amxc_var_init(&locationkey_var); if (amxd_object_get_value(pobj_weather, "LocationKey", &locationkey_var) != 0) { SAH_TRACEZ_WARN(ME, "Failed to read LocationKey."); return -1; } int locationkey = amxc_var_int(&locationkey_var); amxc_var_clean(&locationkey_var); return locationkey; } int get_realtime_info_from_cloud(realtime_weather_info_struct *realtime_weather_info, const char *device_token, const char *url_prefix) { 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; json_object* j_response = NULL; json_object* j_code = 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}; int i =0; int ret = 0; int code = -1; CURL *curl = NULL; struct curl_slist *headers = NULL; int loc_key = 0; char request_data[512] = {0}; char *response = NULL; char request_url[128] = {0}; CURLcode res; st_http_resinfo httpResInfo; SAH_TRACEZ_DEBUG(ME, "Getting real-time weather info from cloud..."); if (realtime_weather_info == NULL || device_token == NULL || url_prefix == NULL) { SAH_TRACEZ_ERROR(ME, "params error"); ret = -1; goto exit; } sprintf(request_url, "%s%s", url_prefix, REALTIME_URL_POSTFIX); curl = curl_easy_init(); if (!curl) { SAH_TRACEZ_ERROR(ME, "Failed to initialize cURL."); ret = -1; goto exit; } headers = curl_slist_append(headers, "Content-Type: application/json"); loc_key = get_location_key(); if (loc_key < 0) { SAH_TRACEZ_ERROR(ME, "Invalid location key."); ret = -1; goto exit; } snprintf(request_data, sizeof(request_data), "{\"locationKey\":%d,\"deviceToken\":\"%s\"}", loc_key, device_token); curl_easy_setopt(curl, CURLOPT_URL, request_url); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request_data); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(curl, CURLOPT_CAINFO, CA_CRT_PATH); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, POST_TRANSFER_TIMEOUT); curl_easy_setopt(curl, CURLOPT_TIMEOUT, POST_CONNECT_TIMEOUT); //CURLOPT needs to be set_ FOLLOWLOCATION is 1, otherwise, the data after redirecting will not be returned curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); res = curl_easy_perform(curl); if (res != CURLE_OK) { SAH_TRACEZ_ERROR(ME, "cURL error: %s", curl_easy_strerror(res)); ret = -1; goto exit; } memset(&httpResInfo, 0, sizeof(st_http_resinfo)); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, httpResInfo.status_code); SAH_TRACEZ_DEBUG(ME, "HTTP Status Code: %ld", httpResInfo.status_code); if (httpResInfo.status_code != 200) { SAH_TRACEZ_WARN(ME, "Non-200 HTTP response received."); ret = -1; goto exit; } json_object *j_response = json_tokener_parse(response); json_object *j_code = json_object_object_get(j_response, "code"); code = json_object_get_int(j_code); if (0 != code) { SAH_TRACEZ_WARN(ME, "Cloud returned error code: %d", code); 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 (message_data && weatherType_data) { if (0 == strcmp(get_temperature_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; } } 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]; } } 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]); } } SAH_TRACEZ_INFO(ME, "Realtime data updated successfully."); 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); } json_object_put(j_response); curl_easy_cleanup(curl); free(response); return ret; } int get_forecast_info_from_cloud(forecast_weather_info_struct *forecast_weather_info, const char *device_token, const char *url_prefix) { 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* forecastList = NULL; json_object* ListItem = NULL; json_object* dayWeatherType = NULL; json_object* nightWeatherType = 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}; const char* dayWeatherType_data = NULL; const char* nightWeatherType_data = NULL; int i =0; int ret = 0; CURL *curl = NULL; struct curl_slist *headers = NULL; int loc_key = 0; char request_data[512] = {0}; char *response = NULL; char request_url[128] = {0}; CURLcode res; st_http_resinfo httpResInfo; SAH_TRACEZ_DEBUG(ME, "Getting real-time weather info from cloud..."); if (forecast_weather_info == NULL || device_token == NULL || url_prefix == NULL) { SAH_TRACEZ_ERROR(ME, "params error"); ret = -1; goto exit; } sprintf(request_url, "%s%s", url_prefix, FORECASTS_URL_POSTFIX); curl = curl_easy_init(); if (!curl) { SAH_TRACEZ_ERROR(ME, "Failed to initialize cURL."); ret = -1; goto exit; } headers = curl_slist_append(headers, "Content-Type: application/json"); loc_key = get_location_key(); if (loc_key < 0) { SAH_TRACEZ_ERROR(ME, "Invalid location key."); ret = -1; goto exit; } snprintf(request_data, sizeof(request_data), "{\"locationKey\":%d,\"deviceToken\":\"%s\"}", loc_key, device_token); curl_easy_setopt(curl, CURLOPT_URL, request_url); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request_data); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); // 10 seconds timeout curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(curl, CURLOPT_CAINFO, CA_CRT_PATH); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, POST_TRANSFER_TIMEOUT); curl_easy_setopt(curl, CURLOPT_TIMEOUT, POST_CONNECT_TIMEOUT); //CURLOPT needs to be set_ FOLLOWLOCATION is 1, otherwise, the data after redirecting will not be returned curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); res = curl_easy_perform(curl); if (res != CURLE_OK) { SAH_TRACEZ_ERROR(ME, "cURL error: %s", curl_easy_strerror(res)); curl_easy_cleanup(curl); ret = -1; goto exit; } memset(&httpResInfo, 0, sizeof(st_http_resinfo)); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, httpResInfo.status_code); SAH_TRACEZ_DEBUG(ME, "HTTP Status Code: %ld", httpResInfo.status_code); if (httpResInfo.status_code != 200) { SAH_TRACEZ_WARN(ME, "Non-200 HTTP response received."); curl_easy_cleanup(curl); return -1; } if (response) { 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) { SAH_TRACEZ_WARN(ME, "Cloud returned error code: %d", errorcode_data); 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 (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); if (dayWeatherType_data && nightWeatherType_data) { if (0 == strcmp(get_temperature_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); } } ret = 0; } } SAH_TRACEZ_INFO(ME, "Forecast data updated successfully."); 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); } json_object_put(j_response); curl_easy_cleanup(curl); free(response); return ret; } static int update_weather_url(void) { char device_token[MAX_TOKEN_LEN] = {0}; char cloud_url[MAX_URL_LEN] = {0}; int i = 0 memset(&realtime_weather_info, 0, sizeof(realtime_weather_info)); for (i = 0; i < 6; i++) { memset(&realtime_weather_info.forecast6Hours[i], 0, sizeof(realtime_weather_info.forecast6Hours[i])); } for (i = 0; i < 3; i++) { memset(&forecast_weather_info[i], 0, sizeof(forecast_weather_info[i])); } if (get_token_url(device_token, cloud_url) != 0) { SAH_TRACEZ_ERROR(ME, "Failed to retrieve token and URL."); return -1; } if (get_realtime_info_from_cloud(&realtime_weather_info, device_token, cloud_url) != 0) { SAH_TRACEZ_ERROR(ME, "Failed to fetch real-time weather data."); return -1; } else { realtime_weather_info.houridx = 0; /* 重置当前小时数 */ SAH_TRACEZ_INFO(ME, "success to fetch real-time weather data."); } if (get_forecast_info_from_cloud(forecast_weather_info, device_token, cloud_url) != 0) { SAH_TRACEZ_ERROR(ME, "Failed to fetch forecast weather data."); return -1; } SAH_TRACEZ_INFO(ME, "All weather data updated successfully."); return 0; } static void config_changed_cb(amxd_object_t *object, amxd_function_t *func, amxc_var_t *args, amxc_var_t *rets) { SAH_TRACEZ_INFO(ME, "Configuration changed. Re-fetching weather data."); update_weather_url(); } static void unit_change_handler(amxd_object_t *obj, amxd_function_t *func, amxc_var_t *args, amxc_var_t *rets) { SAH_TRACEZ_INFO(ME, "Temperature unit changed. Recalculating values."); if (strcmp(get_temperature_unit(), "centigrade") == 0) { g_realtime_weather.temperature = fahrenheit_to_celsius(g_realtime_weather.temperature); g_realtime_weather.temperatureMax = fahrenheit_to_celsius(g_realtime_weather.temperatureMax); g_realtime_weather.temperatureMin = fahrenheit_to_celsius(g_realtime_weather.temperatureMin); for (int i = 0; i < 3; ++i) { g_forecast_weather[i].temperatureMax = fahrenheit_to_celsius(g_forecast_weather[i].temperatureMax); g_forecast_weather[i].temperatureMin = fahrenheit_to_celsius(g_forecast_weather[i].temperatureMin); } } } int save_realtime_weather(realtime_weather_info_struct *weather) { amxd_object_t *pobj_weather = NULL; amxd_object_t *pobj_realtime = NULL; amxd_object_t *hourly_forecast = NULL; pobj_weather = amxd_dm_findf(g_pdm, "X_TP_Weather"); if (!pobj_weather) { SAH_TRACEZ_WARN(ME, "Failed to find X_TP_Weather object."); return -1; } pobj_realtime = amxd_object_get_child(pobj_weather, "Realtime"); if (!pobj_realtime) { SAH_TRACEZ_WARN(ME, "Failed to find X_TP_Weather.Realtime."); return -1; } amxd_object_set_value(uint32_t, pobj_realtime, "Temperature", weather->temperature); amxd_object_set_value(uint32_t, pobj_realtime, "TemperatureMax", weather->temperatureMax); amxd_object_set_value(uint32_t, pobj_realtime, "TemperatureMin", weather->temperatureMin); amxd_object_set_value(string, pobj_realtime, "WeatherType", weather->weatherType); for (int i = 0; i < 6; ++i) { char path[64]; snprintf(path, sizeof(path), "HourlyForecast[%d]", i); hourly_forecast = amxd_object_get_child(pobj_realtime, path); if (!hourly_forecast) { SAH_TRACEZ_WARN(ME, "Failed to find HourlyForecast[%d].", i); continue; } amxd_object_set_value(uint32_t, hourly_forecast, "HourIndex", i); amxd_object_set_value(uint32_t, hourly_forecast, "Temperature", weather->forecast6Hours[i].temperature); amxd_object_set_value(string, hourly_forecast, "WeatherType", weather->forecast6Hours[i].weatherType); } return 0; } int save_forecast_weather(forecast_weather_info_struct *forecasts) { amxd_object_t *pobj_weather = NULL; amxd_object_t *pobj_forecast = NULL; amxd_object_t *day_forecast = NULL; pobj_weather = amxd_dm_findf(g_pdm, "X_TP_Weather"); if (!pobj_weather) { SAH_TRACEZ_WARN(ME, "Failed to find X_TP_Weather object."); return -1; } pobj_forecast = amxd_object_get_child(pobj_weather, "Forecast"); if (!pobj_forecast) { SAH_TRACEZ_WARN(ME, "Failed to find X_TP_Weather.Forecast."); return -1; } for (int i = 0; i < 3; ++i) { char path[64]; snprintf(path, sizeof(path), "Days[%d]", i); day_forecast = amxd_object_get_child(pobj_forecast, path); if (!day_forecast) { SAH_TRACEZ_WARN(ME, "Failed to find Days[%d].", i); continue; } amxd_object_set_value(uint32_t, day_forecast, "DayOffset", i); amxd_object_set_value(uint32_t, day_forecast, "TemperatureMax", forecasts[i].temperatureMax); amxd_object_set_value(uint32_t, day_forecast, "TemperatureMin", forecasts[i].temperatureMin); amxd_object_set_value(string, day_forecast, "DayWeatherType", forecasts[i].dayWeatherType); amxd_object_set_value(string, day_forecast, "NightWeatherType", forecasts[i].nightWeatherType); } return 0; } static void interval_change_handler(amxd_object_t *obj, amxd_function_t *func, amxc_var_t *args, amxc_var_t *rets) { SAH_TRACEZ_INFO(ME, "Update interval changed. Adjusting timer."); uloop_timeout_set(&g_timer, 3600000); } amxd_status_t _weather_update_now(UNUSED amxd_object_t *object, UNUSED amxd_function_t *func, UNUSED amxc_var_t *args, UNUSED amxc_var_t *rets) { SAH_TRACEZ_INFO(ME, "Manual weather update triggered."); update_weather_url(); return amxd_status_ok; } amxd_status_t _weather_start_polling(UNUSED amxd_object_t *object, UNUSED amxd_function_t *func, UNUSED amxc_var_t *args, UNUSED amxc_var_t *rets) { SAH_TRACEZ_INFO(ME, "Starting periodic polling."); uloop_timeout_set(&g_timer, 3600000); // 1 hour return amxd_status_ok; } amxd_status_t _weather_stop_polling(UNUSED amxd_object_t *object, UNUSED amxd_function_t *func, UNUSED amxc_var_t *args, UNUSED amxc_var_t *rets) { SAH_TRACEZ_INFO(ME, "Stopping periodic polling."); uloop_timeout_cancel(&g_timer); return amxd_status_ok; } static void weather_timer_cb(struct uloop_timeout *timer) { SAH_TRACEZ_INFO(ME, "Periodic weather update triggered."); if (update_weather_url() != 0) { SAH_TRACEZ_ERROR(ME, "Failed to update weather data."); uloop_timeout_set(timer, 60000); } else { SAH_TRACEZ_INFO(ME, "Weather data updated successfully."); uloop_timeout_set(timer, 3600000); } } static int weather_init(amxd_dm_t *dm, amxo_parser_t *parser) { amxd_object_t *weather_obj = amxd_dm_findf(dm, "X_TP_Weather"); if (!weather_obj) { return -1; } amxd_object_t *config_obj = amxd_object_get_child(weather_obj, "Config"); if (!config_obj) { return -1; } amxd_object_set_value(uint32_t, config_obj, "LocationKey", 10001); amxd_object_set_value(string, config_obj, "TemperatureUnit", "fahrenheit"); amxd_object_set_value(uint32_t, config_obj, "UpdateInterval", 21600); amxd_object_t *status_obj = amxd_object_get_child(weather_obj, "Status"); if (!status_obj) { return -1; } amxd_object_set_value(bool, status_obj, "IsAvailable", false); amxd_object_set_value(string, status_obj, "LastUpdateTime", ""); amxd_object_set_value(string, status_obj, "CurrentStatus", "Idle"); amxd_object_set_value(uint32_t, status_obj, "ErrorCode", 0); amxd_object_t *realtime_obj = amxd_object_get_child(weather_obj, "Realtime"); if (!realtime_obj) { return -1; } amxd_object_set_value(uint32_t, realtime_obj, "Temperature", 0); amxd_object_set_value(uint32_t, realtime_obj, "TemperatureMax", 0); amxd_object_set_value(uint32_t, realtime_obj, "TemperatureMin", 0); amxd_object_set_value(string, realtime_obj, "WeatherType", ""); amxd_object_t *forecast_obj = amxd_object_get_child(weather_obj, "Forecast"); if (!forecast_obj) { return -1; } amxo_register_function(pparser, "X_TP_Weather.UpdateNow", _weather_update_now, NULL); amxo_register_function(pparser, "X_TP_Weather.StartPolling", _weather_start_polling, NULL); amxo_register_function(pparser, "X_TP_Weather.StopPolling", _weather_stop_polling, NULL); return 0; } int main(int reason, amxd_dm_t *pdm, amxo_parser_t *pparser) { memset(&timer, 0, sizeof(timer)); switch (reason) { case AMXO_START: SAH_TRACEZ_INFO(ME, "Initializing weather module..."); weather_init(pdm, pparser); timer.cb = weather_timer_cb; uloop_timeout_set(&timer, 1000); SAH_TRACEZ_INFO(ME, "Weather module initialized."); break; case AMXO_STOP: SAH_TRACEZ_INFO(ME, "Cleaning up weather module..."); uloop_timeout_cancel(&timer); SAH_TRACEZ_INFO(ME, "Weather module cleaned up."); break; } return 0; } 分析模块实现,和有无问题
12-19
/************************************************************************************************** * Copyright(c) 2009-2022 Shenzhen TP-LINK Technologies Co.Ltd. * * file weather_server.c * brief * details weather report server * * author Tan Rui * version * date 2022.10.10 * * history * ***************************************************************************************************/ #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 { // uci_set_option("global", "error", "get_token_url error"); ERR("get_token_url error"); return -1; } // /* offline test*/ // (void)device_token; // (void)cloud_weather_url; // realtime_weather_info.temperature = 70; // realtime_weather_info.temperatureMax = 90; // realtime_weather_info.temperatureMin = 50; // if (0 == strcmp(uci_get_unit(),"centigrade")) // { // realtime_weather_info.temperature = (realtime_weather_info.temperature - 32) / 1.8; // realtime_weather_info.temperatureMax = (realtime_weather_info.temperatureMax -32) / 1.8; // realtime_weather_info.temperatureMin = (realtime_weather_info.temperatureMin - 32) / 1.8; // } // sprintf(realtime_weather_info.weatherType, "%s", "clear"); // weather_errorcode = 0; // memcpy(weather_message,"none",sizeof("none")); // weather_ubus_update_event_generate(0); // if (1 != uci_renew(0)) // { // ERR("set_realtime_info_to_uci fail"); // return -1; // } // for ( i = 0; i < 3; i++) // { // forecast_weather_info[i].temperatureMax = 91 + i; // forecast_weather_info[i].temperatureMin = 51 + i; // if (0 == strcmp(uci_get_unit(),"centigrade")) // { // forecast_weather_info[i].temperatureMax = (forecast_weather_info[i].temperatureMax - 32) / 1.8; // forecast_weather_info[i].temperatureMin = (forecast_weather_info[i].temperatureMin - 32) / 1.8; // } // sprintf(forecast_weather_info[i].dayWeatherType, "%s", "clear"); // sprintf(forecast_weather_info[i].nightWeatherType, "%s", "rain"); // } // weather_errorcode = 0; // memcpy(weather_message,"none",sizeof("none")); // weather_ubus_update_event_generate(1); // if (1 != uci_renew(1)) // { // ERR("set_forecast_info_to_uci fail"); // return -1; // } // uci_set_option("global", "error", "weather info update success"); 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"); } /* 启动随机延迟 */ // fd = open("/dev/urandom", O_RDONLY); // if (-1 == fd) // { // srand((unsigned int)time(NULL)); // } // else // { // read(fd, (char *) &seed, sizeof(unsigned int)); // srand(seed); // close(fd); // } // sleep(rand() % 300); // DEBUG("random sleep"); /* 通过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; } 参考如上模块,修改weather模块适配tr181,odl见下#include "mod_sahtrace.odl"; %config { name = "xtp-weather"; storage-type = "odl"; storage-path = "${rw_data_path}/${name}"; odl = { dm-load = true, dm-save = true, dm-save-on-changed = true, dm-save-delay = 1000, load-dm-events = true, directory = "${storage-path}/odl" }; sahtrace = { type = "stdout", level = 500 }; trace-zones = { weather = 500 }; %global modules = { fw-directory = "/usr/lib/amx/modules" }; } requires "Device."; import "mod-dmext.so"; import "${name}.so" as "xtp-weather"; include "${name}_definition.odl"; %define{ entry-point xtp-weather.weather_main; } %define { /** * This object contains general information related to weather */ %persistent object X_TP_Weather { /** * Global Feature * LocationKey: Location * TemperatureUnit: centigrade/fahrenheit */ %persistent object Config { %persistent uint32 LocationKey { default 10001; } %persistent string TemperatureUnit { enum = "centigrade", "fahrenheit"; default "fahrenheit"; } %persistent uint32 UpdateInterval { default = 21600; //seconds } } object Status { bool IsAvailable { default = false; } string LastUpdateTime { default = ""; } string CurrentStatus { enum = "Idle", "Updating", "Error"; default = "Idle"; } uint32 ErrorCode { default = 0; } string ErrorMessage { default = ""; } } /** * Real-time weather data * Temperature: Current temperature * WeatherType: sunny/rainy ... * UpdateTime: Last updated timestamp */ %persistent object Realtime { uint32 Temperature { default = 0; } uint32 TemperatureMax { default = 0; } uint32 TemperatureMin { default = 0; } string WeatherType { default = ""; } object HourlyForecast[] { uint32 HourIndex; uint32 Temperature; string WeatherType; } } /** * Weather forecast data */ object Forecast { object Days[] { uint32 DayOffset { description = "day offset (0:tomorrow,1=the day after tomorrow...)"; } uint32 TemperatureMax; uint32 TemperatureMin; string DayWeatherType; string NightWeatherType; } } void UpdateNow(); void StartPolling(); void StopPolling(); // 增加停止轮询方法 } /* object X_TP_Weather */ } %populate { on event "dm:object-changed" call config_changed_cb filter 'path matches "X_TP_Weather\\.Config\\..*"'; on event "dm:object-changed" call unit_change_handler filter 'path matches "X_TP_Weather\\.Config\\.TemperatureUnit"'; on event "dm:object-changed" call interval_change_handler filter 'path matches "X_TP_Weather\\.Config\\.UpdateInterval"'; on event "dm:object-created" call service_started_cb filter 'path matches "X_TP_Weather"'; on event "dm:object-deleted" call service_stopped_cb filter 'path matches "X_TP_Weather"'; on event "WeatherDataUpdated" call data_updated_cb; on event "WeatherUpdateFailed" call update_failed_cb; }
最新发布
12-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值