#include "mbedtls/md.h"
/* for MD5 file verify */
#include "mbedtls/md5.h"
+#include <sys/stat.h>
+#include <time.h>
+
+#define LN_TOKEN_DIR "/user/leiniao/token"
+#define LN_TOKEN_FILE "/user/leiniao/token/device_token.json"
static void ln_to_hex_lower(const uint8_t *in, size_t in_len, char *out)
{
return 0;
}
+/* 创建目录 */
+static void ln_mkdir_p(const char *path)
+{
+ if (!path)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_mkdir_p: path is NULL");
+ return;
+ }
+ (void)mkdir(LN_TOKEN_DIR, 0755);
+}
+
+/* 保存设备Token到本地 */
+static uint32_t ln_token_save_json(const char *token, uint64_t expire_timestamp)
+{
+ if (token == NULL || token[0] == '\0')
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_token_save_json: token is NULL");
+ return ERRCODE_FAIL;
+ }
+ ln_mkdir_p(LN_TOKEN_DIR);
+
+ /* 生成create_time字符串 */
+ char create_time_str[32] = {0};
+ time_t now = time(NULL);
+ struct tm tm_now;
+ (void)localtime_r(&now, &tm_now);
+ (void)strftime(create_time_str, sizeof(create_time_str), "%Y-%m-%d %H:%M:%S", &tm_now);
+
+ cJSON *root = cJSON_CreateObject();
+ cJSON_AddStringToObject(root, "device_token", token);
+ /* 业务约定:expire_timestamp 保存的是“保存时的当前秒级时间戳”,用于与当前时间比较是否超过30天 */
+ cJSON_AddNumberToObject(root, "expire_timestamp", (double)now);
+ cJSON_AddStringToObject(root, "create_time", create_time_str);
+
+ char *text = cJSON_PrintUnformatted(root);
+ cJSON_Delete(root);
+ if (text == NULL)
+ return ERRCODE_FAIL;
+
+ FILE *fp = fopen(LN_TOKEN_FILE, "wb");
+ if (!fp)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_token_save_json: fopen failed");
+ free(text);
+ return ERRCODE_FAIL;
+ }
+ size_t n = fwrite(text, 1, strlen(text), fp);
+ if (n != strlen(text))
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_token_save_json: fwrite failed");
+ fclose(fp);
+ free(text);
+ return ERRCODE_FAIL;
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_token_save_json: fwrite success");
+ /* 打印保存的json */
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_token_save_json: save json=%s", text);
+ fclose(fp);
+ free(text);
+ return (n > 0) ? ERRCODE_SUCC : ERRCODE_FAIL;
+}
+
+uint32_t ln_token_load_json(char **token_out, uint64_t *expire_timestamp_out)
+{
+ if (token_out)
+ *token_out = NULL;
+ if (expire_timestamp_out)
+ *expire_timestamp_out = 0;
+
+ FILE *fp = fopen(LN_TOKEN_FILE, "rb");
+ if (!fp)
+ return ERRCODE_FAIL;
+ fseek(fp, 0, SEEK_END);
+ long len = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ if (len <= 0 || len > 64 * 1024)
+ {
+ fclose(fp);
+ return ERRCODE_FAIL;
+ }
+ char *buf = (char *)malloc((size_t)len + 1);
+ if (!buf)
+ {
+ fclose(fp);
+ return ERRCODE_FAIL;
+ }
+ size_t n = fread(buf, 1, (size_t)len, fp);
+ fclose(fp);
+ buf[n] = '\0';
+
+ cJSON *root = cJSON_Parse(buf);
+ if (!root)
+ {
+ free(buf);
+ return ERRCODE_FAIL;
+ }
+ cJSON *tok = cJSON_GetObjectItem(root, "device_token");
+ cJSON *exp = cJSON_GetObjectItem(root, "expire_timestamp");
+ if (tok && cJSON_IsString(tok) && token_out)
+ {
+ *token_out = strdup(tok->valuestring);
+ }
+ if (exp && cJSON_IsNumber(exp) && expire_timestamp_out)
+ {
+ *expire_timestamp_out = (uint64_t)exp->valuedouble;
+ }
+ cJSON_Delete(root);
+ free(buf);
+ return ERRCODE_SUCC;
+}
+
+uint32_t uapi_ln_refresh_device_token(void)
+{
+ return ln_get_device_token_http(uapi_ln_get_device_id(),
+ uapi_ln_get_device_iccid(),
+ uapi_ln_get_device_model(),
+ uapi_ln_get_device_version());
+}
+
+/*
+ * 判断本地缓存的 token 是否过期(按约定:expire_timestamp 存的是保存时的当前秒级时间戳)
+ * 规则:now - expire_timestamp > 2592000(30天) 则过期
+ */
+uint32_t ln_token_is_expired(int *expired_out)
+{
+ if (expired_out) *expired_out = 1; /* 默认过期 */
+
+ FILE *fp = fopen(LN_TOKEN_FILE, "rb");
+ if (!fp) return ERRCODE_FAIL;
+ fseek(fp, 0, SEEK_END);
+ long len = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ if (len <= 0 || len > 64 * 1024) { fclose(fp); return ERRCODE_FAIL; }
+ char *buf = (char*)malloc((size_t)len + 1);
+ if (!buf) { fclose(fp); return ERRCODE_FAIL; }
+ size_t n = fread(buf, 1, (size_t)len, fp);
+ fclose(fp);
+ buf[n] = '\0';
+
+ cJSON *root = cJSON_Parse(buf);
+ if (!root) { free(buf); return ERRCODE_FAIL; }
+ cJSON *exp = cJSON_GetObjectItem(root, "expire_timestamp");
+ time_t now_s = time(NULL);
+ int expired = 1; /* 默认过期 */
+ if (exp && cJSON_IsNumber(exp)) {
+ uint64_t saved_ts = (uint64_t)exp->valuedouble; /* 保存时的当前时间戳(秒) */
+ const uint64_t TTL_30D = 2592000ULL; /* 30 * 24 * 3600 */
+ expired = ((uint64_t)now_s - saved_ts > TTL_30D) ? 1 : 0;
+ }
+
+ if (expired_out) *expired_out = expired;
+ cJSON_Delete(root);
+ free(buf);
+ return ERRCODE_SUCC;
+}
+
/* 生成[a-zA-Z0-9]随机串 */
static void ln_gen_nonce(char *out, size_t len)
{
{
if (device_id == NULL || device_iccid == NULL)
{
- printf("LN token: invalid parameters\n");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: invalid parameters");
return ERRCODE_FAIL;
}
char signature[65] = {0};
if (ln_hmac_sha256_hex(LN_SIGN_SECRET, sign_data, signature, sizeof(signature)) != 0)
{
- printf("LN token: hmac calc failed\n");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: hmac calc failed");
return ERRCODE_FAIL;
}
(device_version && device_version[0]) ? device_version : "1.0.0");
if (hdr_len <= 0 || hdr_len >= (int)sizeof(header_buf))
{
- printf("LN token: header build failed\n");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: header build failed");
return ERRCODE_FAIL;
}
- #ifdef SUPPORT_CAT1_SERVICE
+#ifdef SUPPORT_CAT1_SERVICE
/* 4. 保活CAT1,准备网络 */
cat1_api_add_cat1_vote();
cat1_api_wakeup_cat1(1);
cat1_api_keep_wakeup(1);
cat1_api_disable_cat1_cmd(1);
LOS_Msleep(500);
- #endif
+#endif
/* 5. 发起HTTPS GET */
HttpClient client = (HttpClient){0};
HTTPC_RESULT prep = HttpClientPrepare(&clientData, 2048, 4096);
if (prep != HTTP_SUCCESS)
{
- printf("LN token: HttpClientPrepare failed %d\n", prep);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: HttpClientPrepare failed %d", prep);
return ERRCODE_FAIL;
}
HTTPC_RESULT res = HttpClientGetRequest(&client, LN_FULL_URL, &clientData);
if (res != HTTP_SUCCESS)
{
- printf("LN token: request failed %d\n", res);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: request failed %d", res);
HttpClientUnprepare(&clientData);
HttpClientClse(&client);
return ERRCODE_FAIL;
int code = HttpClientGetResponseCode(&client);
if (code != 200)
{
- printf("LN token: HTTP %d\n", code);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: HTTP %d", code);
HttpClientUnprepare(&clientData);
HttpClientClse(&client);
return ERRCODE_FAIL;
/* 6. 解析响应JSON */
if (clientData.responseBuf == NULL || clientData.responseBufLen <= 0)
{
- printf("LN token: empty body\n");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: empty body");
HttpClientUnprepare(&clientData);
HttpClientClse(&client);
return ERRCODE_FAIL;
cJSON *root = cJSON_Parse(json_text);
if (!root)
{
- printf("LN token: JSON parse failed\n");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: JSON parse failed");
free(json_text);
HttpClientUnprepare(&clientData);
HttpClientClse(&client);
if (errorCode != NULL && !cJSON_IsNull(errorCode))
{
cJSON *msg = cJSON_GetObjectItem(root, "message");
- printf("LN token: failed, err=%s\n", msg && cJSON_IsString(msg) ? msg->valuestring : "unknown");
+ /* 失败响应,打印errorCode和message 并返回失败 */
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: failed, err=%s", errorCode && cJSON_IsString(errorCode) ? errorCode->valuestring : "unknown");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: failed, message=%s", msg && cJSON_IsString(msg) ? msg->valuestring : "unknown");
cJSON_Delete(root);
free(json_text);
HttpClientUnprepare(&clientData);
{
g_device_token = strdup("<null>");
}
- printf("\njson=%s\n", json_text);
+ /* 落盘保存 */
+ uint64_t exp_ts = 0;
if (expire && cJSON_IsNumber(expire))
{
- printf("Token expireTime: %lld\n", (long long)expire->valuedouble);
+ exp_ts = (uint64_t)expire->valuedouble;
}
+ (void)ln_token_save_json(g_device_token, exp_ts);
}
else
{
- printf("LN token: no data field\n");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_get_device_token_http: no data field");
}
cJSON_Delete(root);