/*
 * @Author: ybzhou yibo.zhou@lnxall.com
 * @Date: 2025-05-22 22:36:26
 * @LastEditors: ybzhou yibo.zhou@lnxall.com
 * @LastEditTime: 2025-07-07 16:44:20
 * @FilePath: /my_ota/proto_forward/src/ota_upgrade/ota_upgrade.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef _OTA_UPGRADE_H
#define _OTA_UPGRADE_H

#include <time.h>
#include <pthread.h>

#include "../mqtt_emms2/mqtt_emms2.h"
#include "interact.h"
#include "interface.h"

#define MAX_KV_PAIRS 32

#define OTA_FILE_MAX 10
#define OTA_INFO_FILE          "ota_info.json" // 缓存升级信息

#define OTA_UPGRADE_DIR        "/app/temp/ota"
#define OTA_UPGRADE_SCRIPT_DIR "/opt/lnxall_app/bin/"

#define FUNCTION_ID_OTAUPDATE  "OtaUpdate"
#define FUNCTION_ID_OTACOURSE  "OtaCourse"

#define FUNCTION_TYPE_GET      "Get"
#define FUNCTION_TYPE_GETRESP  "GetResp"
#define FUNCTION_TYPE_SET      "Set"
#define FUNCTION_TYPE_SETRESP  "SetResp"
#define FUNCTION_TYPE_POST     "LcPost"
#define FUNCTION_TYPE_POSTRESP "LcPostResp"

typedef struct {
    time_t last_report_time;
    double last_dlnow;
    char   current_file[256];    // 当前下载文件名
    int    flag;
} download_progress_t;

typedef int (*ota_download_callback_t)(void* clientp, double dltotal, double dlnow, double ultotal, double ulnow);

typedef enum
{
    OTA_TERM_UPGRADE_READY = 0,
    OTA_TERM_DOWNLOAD_FAIL = 401, // 文件下载失败
    OTA_TERM_CHECK_FAIL,          // MD5校验失败
    OTA_TERM_NO_ONLINE_DEV,
    OTA_TERM_UPGRADE_TIMEOUT,
    OTA_TERM_EXECUTE_UPGRADE,
    OTA_TERM_INIT_DEV_STATE_FAIL,
    OTA_TERM_READ_FIRMWARE_FAIL,
    OTA_TERM_CUT_BLOCK_FAIL,
    OTA_TERM_SEND_START_FAIL,
    OTA_TERM_SEND_BLOCK_FAIL,
    OTA_TERM_ALREADY_RUN,       // 已处于升级中
    OTA_TERM_ALREADY_STOP,      // 已结束升级
    OTA_TERM_PARSE_FAILED,      // 升级参数解析错误
    OTA_TERM_UPGRADE_ABORT,
    OTA_TERM_INTERNAL_FAULT,    // 内部错误
    OTA_TERM_SCRIPT_START_FAIL, // 升级脚本启动失败
    OTA_TERM_SCRIPT_ERROR,      // 升级脚本崩溃
    OTA_TERM_NOMANUAL_OR_POWER, // 非手动模式 OR 处于充放电状态
    OTA_TERM_ACK_ERROR_OR_TIMEOUT, // 升级ACK错误 OR 超时
    OTA_TERM_VER_CHECK_FAIL,    // 版本校验错误
    OTA_TERM_USER_STOP,         // 用户主动停止
    OTA_TERM_TIMEOUT_EXIT,      // 超时退出
    OTA_TERM_UNSUPPORT_CMD,     // 不支持的命令
    OTA_TERM_CHANNEL_BUSY,      // 通道忙
    OTA_TERM_READY_RUN,         // 还未开始升级，可能在下载固件，此时不能发中断升级操作
    OTA_TERM_UPGRADE_DONE,
} ota_term_code;

// Example: "port=RS485_2;"
typedef struct {
    char key[32];    // 存储 "=" 前的部分（如 "port"）
    char value[32];  // 存储 "=" 后的部分（如 "RS485_2"）
} keyvalue_t;

typedef struct {
    char *user_def;
    int kv_num;
    keyvalue_t kv_pairs[0];
}argv_t;

typedef struct ota_info
{
    char** file;
    char** file_urls;
    char** file_md5s;
    int    file_num;
    //char** argv;
    //int    argc;
    argv_t *argv;
    char   script[256];
    time_t start;
    time_t end;
    char   *tmp[OTA_FILE_MAX]; // 升级文件临时存放目录
} ota_info_t;

typedef enum
{
	OTA_UPGRADE_IDLE,
	OTA_UPGRADING_GW,	 // 升级网关
	OTA_UPGRADING_APP,   // 升级APP
    OTA_UPGRADING_NODE,  // 下挂设备升级中
} ota_state_t;

typedef struct ota_param
{
    char       dev_no[32];
    channel_t*    chan_pr;
    device_t*      dev_pr;

    interact_t* interact;
    ota_hd_t         *hd;

    void*  info;       // 升级信息
    int    seq;
    int    mode;       // 升级方式，0:串行升级 1:并行升级
    int    same;       // 0:升级接口与通信接口一致  1：不一致
    char   cmd[128];   // 升级命令，start:开始  stop:终止
    ota_state_t state; // 升级状态
    void *var;         // emms2云信息
} ota_param_t;

ota_param_t *get_ota_param(void);

keyvalue_t *check_port_inpair(ota_info_t *info);

int mqtt_otalog_publish(uint8_t levl, char *content);
int mqtt_otaprogress_publish(float progress, uint8_t indx);
int mqtt_otaend_publish(mqtt_emms2_var_t *var, char *dev_no, int code, char *ver, int seq);

void free_ota_param(ota_param_t *ota_param);
int ota_upgrade_cmd(mqtt_emms2_var_t* var, cJSON* root, int seq);

#endif
