weather

博客提供了一个天气服务插件的链接,即http://service.weather.com.cn/plugin/index.shtml ,可通过该链接访问相关天气服务插件。
Enviro - The complete dynamic AAA sky and weather solution! Very easy setup: The new manager component makes it easy as possible to setup enviro in your scenes. Includes Enviro Lite! This version includes Enviro Lite version aswell. Ideal for multi-platform projects: Use lite version for low end platform like mobiles and standard for pc and consoles. With one click you can switch between enviro versions. The centralized API for your own scripts will work for both versions of course. Profile System: Enviro's new profile system makes tweaking your sky as easy as possible. Tweak settings in runtime and save to profile. Load profiles in design and runtime. Create different profiles for different scenes or share your configurations with other user. Day-Night cycle: Enviro supports a realistic day-night cycle. With correct sun and moon positions with full location support with latitude and longitude. You have options to use your system time or let enviro update time based on realtime minutes. Skybox: Enviro includes an advanced fast atmospheric skybox shader to get great looking skies! You got a lot of options to tweak the sky and even can setup funky alien skies! Lighting: Enviro will realisticly light your scene based on sun altitude. You have complete control over light intensity and color by modifying curves and gradients right in editor! You also can choose between different ambient light modes of course. Seasons: Enviro will change seasons and got a components to swap out gameobject, materials and textures of unity terrain. You are not limited to realistic settings! You can set the start and end days of each season. Enviro also supports temperature simulation, based on season, time of day and current weather. Clouds: Enviro new raymarching cloud system is based on latest cloud rendering papers. These will bring you sky to life and offer plenty options to customize. Clouds performance is optimized by using techs like temporal reprojection and LOD system. In addition there are also fast flat and particle clouds options to mix or use for maximum performance. Fog: Need stunnishing looking fog? Enviro includes an advanced light scattering fog image effect with distance, height and sky fog support. Need fog on your transparent material? No problem, with only a few lines of code you could modify your own transparent shaders to be fogged correctly. And a few particle and transparent shaders already included to get you started! Weather: Enviro includes a very powerfull weather system. You can create your own weather types and drive light, sky, fog and clouds. Enviro supports all kind of unity shuriken particle effects to give you the freedom to create any weather effect you can think of. It includes 11 premade weather types including: Clear Sky, cloudy, raining, stormy, snowy and foggy weather. You can enable lightning storms and choose different ambient and weather sounds for each weather with smooth transitions. Volumetric Lighting: Need some volume light effects you see in AAA games? No problem, enviro support volumetric lighting for directional, point and spot lights out of the box! Scene View Effects: Preview enviro effects like clouds, volume lighting and fog directly while you work on your scenes. You can enable or disable scene view preview for each effect individual of course. Networking: Enviro support UNet, Mirror and Photon out of the box. It will synchronize time and weather with all your players. Enviro also got an minimal mode for headless servers to only calculate time and weather but nothing more. Virtual Reality: Enviro supports multi and singlepass stereoscopic rendering! Tested on Oculus Rift. That's not all! Enviro includes a lot more great features: * Event system for you game logic. * Weather Zones. Create as many zones with their own weather for your biomes. * Orbiting satellites. * Vegetation Growth. And you can use a lot of awesome 3rd-party assets right of the box. Activate and add 3rd-party support through the new interface. Again its easy and fast as possible! * Gaia Compatible! * CTS Compatible! * AQUAS Integration! * LUX Water Integration! * FogVolume 3 Integration! * Vegetation Studio Pro Integration! * Playmaker Actions! * Relief Terrain Shader Integration! * UBER Shader Integration! * MicroSplat Integration! * MegaSplat Shader Integration! * Lux Shader Integration! * Photon Network Integration! * Mirror Network Integration! * Pegasus Integration! Requirements: * Support gamma and linear color space. * Support forward and deferred rendering. * Working on DX9, DX11, DX12, OpenGlCore, Metal and Vulkan. * Volumetric Lighting requires at least shader-model 3.5+ and will be deactivated on DX9 Current limitation: * Volumetric clouds are currently not suitable for fly-throughs! Will be worked on in later updates!
插件名称:Enviro - Sky and Weather 2.0 Enviro - The complete dynamic AAA sky and weather solution! Very easy setup: Just drag-and drop into your scene and assign your main camera or use the runtime assignment features. Profile System: Enviro's new profile system makes tweaking your sky as easy as possible. Tweak settings in runtime and save to profile. Load profiles in design and runtime. Create different profiles for different scenes or share your configurations with other user. Day-Night cycle: Enviro supports a realistic day-night cycle. With correct sun and moon positions with full location support with latitude and longitude. You have options to use your system time or let enviro update time based on realtime minutes. Skybox: Enviro includes an advanced fast atmospheric skybox shader to get great looking skies! You got a lot of options to tweak the sky and even can setup funky alien skies! Lighting: Enviro will realisticly light your scene based on sun altitude. You have complete control over light intensity and color by modifying curves and gradients right in editor! You also can choose between different ambient light modes of course. Seasons: Enviro will change seasons and got a components to swap out gameobject, materials and textures of unity terrain. You are not limited to realistic settings! You can set the amount of days each season last. Clouds: Enviro new volumetric cloud system is based on latest cloud rendering papers. These will bring you sky to life and offer plenty options to customize. In addition there are also fast flat clouds options to mix or use for maximum performance. Fog: Need stunnishing looking fog? Enviro includes an advanced light scattering fog image effect with distance, height and sky fog support. Need fog on your transparent material? No problem, with only a few lines of code you could modify your own transparent shaders to be fogged correctly. And a few particle and transparent shaders already included to get you started! Volumetric Lighting: Need some volume light effects you see in AAA games? No problem, enviro support volumetric lihting for directional, point and spot lights out of the box! Weather: Enviro includes a very powerfull weather system. You can create your own weather types and drive light, sky, fog and clouds. Enviro supports all kind of unity shuriken particle effects to give you the freedom to create any weather effect you can think of. It includes 11 premade weather types including: Clear Sky, cloudy, raining, stormy, snowy and foggy weather. You can enable lightning storms and choose different ambient and weather sounds for each weather with smooth transitions. Networking: Enviro support UNet and Photon out of the box. It will synchronize time and weather with all your players. Enviro also got an minimal mode for headless servers to only calculate time and weather but nothing more. Virtual Reality: Enviro supports multi and singlepass stereoscopic rendering! Tested on Oculus Rift. (Attention: Singlepass currently only supported on Unity 2017+ !) That's not all! Enviro includes a lot more great features: * Event system for you game logic. * Weather Zones. Create as many zones with their own weather for your biomes. * Orbiting satellites. * Vegetation Growth. And you can use a lot of awesome 3rd-party assets right of the box with the included enviro components: * Gaia Compatible! * CTS Compatible! * AQUAS Integration! * FogVolume 3 Integration! * Playmaker Actions! * Relief Terrain Shader Integration! * UBER Shader Integration! * MegaSplat Shader Integration! * Lux Shader Integration! * Photon Network Integration! * Pegasus Integration! Requirements: * Support gamma and linear color space. * Support forward and deferred rendering. * Working on DX9, DX11, DX12, OpenGlCore, Metal and Vulkan. * Volumetric Lighting requires at least shader-model 3.5+ and will be deactivated on DX9 Current limitation: * Volumetric clouds are currently not suitable for fly-throughs! Will be worked on in later updates! WebGL Demo Forum Thread
Enviro - 完整的动态AAA天空和天气解决方案! 非常简单的设置: 只需拖放到您的场景中,分配您的主摄像头或使用运行时分配功能。 配置文件系统: Enviro的新配置文件系统可以尽可能简单地调整你的天空。在运行时调整设置并保存到配置文件。在设计和运行时加载配置文件。为不同的场景创建不同的配置文件或与其他用户共享您的配置。 日夜循环: Enviro支持逼真的夜间循环。具有正确的太阳和月亮位置以及全方位的经纬度支持。你可以选择使用你的系统时间,或根据实时分钟让enviro更新时间。 空中包厢: Enviro包括一个先进的快速大气天空箱着色器,以获得美丽的天空!你有很多选择来调整天空,甚至可以设置时髦的外星人的天空! 照明: Enviro会根据太阳高度真实地照亮您的场景。通过在编辑器中修改曲线和渐变,您可以完全控制光线强度和颜色!您当然也可以选择不同的环境光模式。 季节: Enviro将改变季节,并有一个组件来换取游戏对象,材料和团结地形的纹理。你不仅限于现实的设置!您可以设置每个赛季的最后天数。 云: Enviro新的容积云系统基于最新的云渲染论文。这些将带给你生命的天空,并提供丰富的选项来定制。此外,还有快速平坦的云层选项可以混合或使用,以实现最佳性能。 雾: 需要惊人的看起来雾?Enviro具有高级光散射雾影像效果,支持距离,高度和天空雾。您的透明材质需要雾?没问题,只需要几行代码就可以修改自己的透明着色器,使其正确模糊。并且已经包含一些粒子和透明着色器以帮助您开始! 体积照明: 需要在AAA游戏中看到一些音量灯光效果?没问题,enviro支持定向,点和射灯箱体积立体化! 天气: Enviro包括一个非常强大的天气系统。您可以创建自己的天气类型,并驱动光线,天空,雾和云。Enviro支持所有类型的统一shuriken粒子效果,使您可以自由创建任何您能想到的天气效果。它包括11种预制天气类型,包括:晴朗天空,多云,下雨,暴风雨,下雪和有雾的天气。您可以启用闪电风暴,并为每个天气选择不同的环境和天气声音,并进行平滑过渡。 网络: Enviro支持UNet和Photon开箱即用。它将与所有玩家同步时间和天气。Enviro还为无头服务器提供了最低限度的模式,只计算时间和天气,但仅此而已。 虚拟现实: Enviro支持多通道和单通道立体渲染!经过Oculus Rift测试。(注意:Singlepass目前仅支持Unity 2017+!) 这还不是全部!Enviro包含许多更好的功能: *游戏逻辑的事件系统。 *天气区。为您的生物群组创建与自己的天气一样多的区域。 *轨道卫星。 *植被生长。 资源名称: Sky and Weather v2.3.1(2020/10/4更新) 资源版本:v2.3.1 资源类型: .unitypackage 资源大小: 192 MB 支持版本:5.6.0及以上版本
结合原实现重新整理下,有点不对 #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; }注意向云获取天气信息和解析的逻辑不要忽略,注意添加SAH_TRACEZ_ERROR等log
最新发布
12-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值