/*
 * @Author: ybzhou yibo.zhou@lnxall.com
 * @Date: 2025-05-22 15:45:59
 * @LastEditors: ybzhou yibo.zhou@lnxall.com
 * @LastEditTime: 2025-11-03 16:20:56
 * @FilePath: /upgrade_simple/upgrade.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef __INTERACT_H
#define __INTERACT_H

#include <semaphore.h>

#include <sys/wait.h>
#include <signal.h>

#define _EXIT_SUCCESS 0
#define _EXIT_FAILURE 1
#define _EXIT_SIGINT 2
#define _EXIT_SIGKILL 9
#define _EXIT_SIGTERM 15

// 错误退出	os.exit(1)	1-127	自定义错误码
// 信号转退出码的宏（遵循 128 + signo 惯例）
#define W_EXITCODE_SIGNAL(sig) ((sig) + 128)

#define W_IS_SIGNALED_EXIT(exit_code) ((exit_code) > 128 && (exit_code) < (128 + NSIG))
#define W_GET_SIGNAL_FROM_EXIT(exit_code) ((exit_code) - 128)

// 检查是否因特定信号退出
#define W_EXITED_BY_SIGNAL(exit_code, sig) (W_IS_SIGNALED_EXIT(exit_code) && \
                                           (W_GET_SIGNAL_FROM_EXIT(exit_code) == (sig)))

#define W_EXITCODE_SIGTERM W_EXITCODE_SIGNAL(_EXIT_SIGTERM)  // 143 (128 + 15)
#define W_EXITCODE_SIGINT  W_EXITCODE_SIGNAL(_EXIT_SIGINT)   // 130 (128 + 2)
#define W_EXITCODE_SIGKILL W_EXITCODE_SIGNAL(_EXIT_SIGKILL)  // 137 (128 + 9)

//------------------------------------------------------------------------
#define LOG_CHUNK_SIZE 512  // 每块最大长度
#define ENABLE_LOG_REPORT 0 // 是否使能升级脚本log上云，默认：0 不使能

#define TIMEOUT_SEC 1
#define LOG_TIMEOUT_SEC 2
#define BUF_SIZE 4 * 1024

/*
 0      1      2      3      4      4+data_len  4+data_len+2
+------+------+------+------+------+-----------+-----------+
| 0xAA | timeout (LE) | len |  data...  | CRC16 (Modbus) |
+------+------+------+------+------+-----------+-----------+
*/
typedef struct {
    uint8_t  header;     // 0xAA
    uint16_t timeout;    // 小端
    uint16_t len;        // 数据长度
    uint8_t  data[];     // 可变长度数据
    // CRC16 在帧末尾（不包含在结构中）
}__attribute__((packed)) frame_t;

#define FRAME_HEADER       0xAA
#define FRAME_META_SIZE    sizeof(frame_t)        // 4字节
#define FRAME_MIN_SIZE     (FRAME_META_SIZE + 2)  // 最小帧长度（含CRC）
#define FRAME_MAX_DATA     256                    // 数据区最大长度

typedef struct{
    uint32_t    pos;
    uint8_t buff[0];
} command_t;

typedef struct{
    uint32_t pos;
    char buff[0];
} log_t;

typedef enum {
    U_SUCCESS = 1,
    U_FAIL,
    U_PROGRESS,
} UPGRADE_SIGN;

#define VALID_MSG_TYPE(type) ((type) == U_SUCCESS || (type) == U_FAIL || (type) == U_PROGRESS)

typedef struct{
    uint8_t msg_type;
    float   progress;
    uint8_t     indx;   // 当前升级文件的索引 lua->C(告知C当前升级的是哪个固件)
    char    ver[128];
}__attribute__((packed)) progress_msg_t;

typedef struct{
    uint32_t        used;
    progress_msg_t msg[0];
} msg_t;

typedef enum {
    COMMAND_INDEX = 0,
    RESPONSE_INDEX,
    PROGRESS_INDEX,
    LOG_INDEX,
    MAX_INDEX,
} PIPE_INDEX;

#define PIPE_COMMAND   "/tmp/command"    // Lua → C
#define PIPE_RESPONSE  "/tmp/response"   // C → Lua
#define PIPE_PROGRESS  "/tmp/progress"   // Lua → C
#define PIPE_LOG       "/tmp/log"        // Lua → C

typedef struct {
    int         fd; // 管道文件描述符
    char path[128]; // 管道路径
} pipe_info;

typedef struct {
    pipe_info pipes[MAX_INDEX];
    int num;

    pthread_t tid;
    pthread_t l_tid;
    pthread_t monitor;  // 监控线程
    pid_t child_pid;    // lua子进程pid    
    sem_t *sem;
    volatile int thread_exit_flag;  // 线程退出标志
} interact_t;

interact_t* script_interact_init(void);
void script_interact_free(interact_t* interact);
void log_lua_error(void);

#endif
