改进前:

// 全量校验:所有属性都必须存在,缺一个就失败
int Zlink_SetIotPro(const PropertySet *all_props, int prop_count)
{
    // 必须包含所有属性才算成功
    if (prop_count != PROP_TOTAL_COUNT) {
        log_error("property count mismatch: got %d, expect %d\n",
                  prop_count, PROP_TOTAL_COUNT);
        return -1;  // App只请求了2个属性 → 直接失败!
    }

    // 全部通过才处理
    for (int i = 0; i < prop_count; i++) {
        process_property(&all_props[i]);
    }
    return 0;
}

改进后:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// ============ 属性定义 ============
typedef enum {
    PROP_COVER_URL    = 0,   // 封面URL
    PROP_COVER_STATUS = 1,   // 封面状态
    PROP_PLAY_URL     = 2,   // 播放地址
    PROP_STORAGE_TYPE = 3,   // 存储类型
    PROP_RECORD_MODE  = 4,   // 录像模式
    PROP_TOTAL_COUNT  = 5    // 属性总数
} PropertyID;

// 属性数据结构
typedef struct {
    PropertyID id;
    char value[256];
} Property;

// ============ 各属性的独立处理函数 ============

// 获取封面URL
int get_cover_url(char *buf, int buf_len)
{
    snprintf(buf, buf_len, "https://cloud.zte.com/cover/2024/xxx.jpg");
    printf("  [处理] 获取封面URL: %s\n", buf);
    return 0;
}

// 获取封面状态
int get_cover_status(char *buf, int buf_len)
{
    snprintf(buf, buf_len, "ready");
    printf("  [处理] 获取封面状态: %s\n", buf);
    return 0;
}

// 获取播放地址
int get_play_url(char *buf, int buf_len)
{
    snprintf(buf, buf_len, "rtsp://192.168.1.100:554/live");
    printf("  [处理] 获取播放地址: %s\n", buf);
    return 0;
}

// 获取存储类型
int get_storage_type(char *buf, int buf_len)
{
    snprintf(buf, buf_len, "cloud");
    printf("  [处理] 获取存储类型: %s\n", buf);
    return 0;
}

// 获取录像模式
int get_record_mode(char *buf, int buf_len)
{
    snprintf(buf, buf_len, "event");
    printf("  [处理] 获取录像模式: %s\n", buf);
    return 0;
}

// ============ 核心:属性-函数映射表 ============

// 函数指针类型
typedef int (*PropGetFunc)(char *buf, int buf_len);

// 映射表:属性ID → 对应的处理函数
typedef struct {
    PropertyID   id;
    const char  *name;
    PropGetFunc  get_func;    // 获取函数
    // 也可以加 set_func 用于下发
} PropMapEntry;

// 映射表定义(新增属性只需加一行)
static PropMapEntry prop_map_table[PROP_TOTAL_COUNT] = {
    { PROP_COVER_URL,    "cover_url",    get_cover_url    },
    { PROP_COVER_STATUS, "cover_status", get_cover_status },
    { PROP_PLAY_URL,     "play_url",     get_play_url     },
    { PROP_STORAGE_TYPE, "storage_type", get_storage_type },
    { PROP_RECORD_MODE,  "record_mode",  get_record_mode  },
};

// ============ 重构后的接口:按需调用 ============

// 改造后的接口:只处理App请求的属性
int Zlink_SetIotPro(const PropertyID *req_ids, int req_count,
                    Property *out_props, int *out_count)
{
    *out_count = 0;

    // 遍历App请求的每一个属性
    for (int i = 0; i < req_count; i++) {
        PropertyID id = req_ids[i];

        // 越界检查
        if (id < 0 || id >= PROP_TOTAL_COUNT) {
            log_error("unknown property id: %d\n", id);
            continue;  // 跳过未知属性,不影响其他属性
        }

        // 查映射表,调用对应函数
        PropMapEntry *entry = &prop_map_table[id];

        out_props[*out_count].id = id;
        int ret = entry->get_func(out_props[*out_count].value,
                                   sizeof(out_props[*out_count].value));
        if (ret == 0) {
            printf("  属性[%s] 获取成功\n", entry->name);
            (*out_count)++;
        } else {
            printf("  属性[%s] 获取失败\n", entry->name);
        }
    }

    return (*out_count > 0) ? 0 : -1;
    // 只要有至少一个属性成功就返回成功
    // 不再要求全量通过
}

// ============ 测试 ============

int main(void)
{
    // 场景1:App只请求封面相关的2个属性(之前会失败,现在成功)
    printf("=== 场景1:App只请求封面URL和封面状态 ===\n");
    PropertyID req1[] = { PROP_COVER_URL, PROP_COVER_STATUS };
    Property out1[PROP_TOTAL_COUNT];
    int out1_count = 0;

    int ret1 = Zlink_SetIotPro(req1, 2, out1, &out1_count);
    printf("结果: ret=%d, 获取到%d个属性\n\n", ret1, out1_count);

    // 场景2:App请求全部属性
    printf("=== 场景2:App请求全部属性 ===\n");
    PropertyID req2[] = { PROP_COVER_URL, PROP_COVER_STATUS, PROP_PLAY_URL,
                          PROP_STORAGE_TYPE, PROP_RECORD_MODE };
    Property out2[PROP_TOTAL_COUNT];
    int out2_count = 0;

    int ret2 = Zlink_SetIotPro(req2, 5, out2, &out2_count);
    printf("结果: ret=%d, 获取到%d个属性\n", ret2, out2_count);

    return 0;
}

更多推荐