分析
/*************************************************************************************************/
/* INCLUDE_FILES */
/*************************************************************************************************/
#include "weather_server.h"
/**************************************************************************************************/
/* DEFINES */
/**************************************************************************************************/
#define ME "weather"
/**************************************************************************************************/
/* 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;
const char* unit = 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;
}
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_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;
}
response_json = json_tokener_parse(response);
j_code = json_object_object_get(response_json, "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;
}
if (response == NULL)
{
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);
}
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;
const char* weatherType_data = 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);
}
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(&g_realtime_weather, 0, sizeof(g_realtime_weather));
for (i = 0; i < 6; i++) {
memset(&g_realtime_weather.forecast6Hours[i], 0, sizeof(g_realtime_weather.forecast6Hours[i]));
}
for (i = 0; i < 3; i++) {
memset(&g_forecast_weather[i], 0, sizeof(g_forecast_weather[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(&g_realtime_weather, device_token, cloud_url) != 0) {
SAH_TRACEZ_ERROR(ME, "Failed to fetch real-time weather data.");
return -1;
}
else {
g_realtime_weather.houridx = 0; /* 重置当前小时数 */
SAH_TRACEZ_INFO(ME, "success to fetch real-time weather data.");
}
if (get_forecast_info_from_cloud(g_forecast_weather, 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(parser, "X_TP_Weather.UpdateNow", _weather_update_now, NULL);
amxo_register_function(parser, "X_TP_Weather.StartPolling", _weather_start_polling, NULL);
amxo_register_function(parser, "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;
}
最新发布