生成代码包

This commit is contained in:
2026-09-09 10:29:41 +08:00
commit 900c5339e2
905 changed files with 216635 additions and 0 deletions
+383
View File
@@ -0,0 +1,383 @@
/* ================================================================
* jb_product.c — 用户层实现(请填补空白处)
* 设备: 喷淋器 | 生成时间: 2026-09-09 10:22:58
*
* ══ 开发流程 ══
* 1. 实现硬件抽象: jbGetTimerCount(定时器由 SOC SDK 提供)
* 发送由 SOC SDK 的 ble_send_data 承担,协议层已直接调用,无需 uartWrite
* 2. userInit() 设置 DP 默认值与外设初始化
* 3. userHandle() 用户数据采集
* 4. jbEventProcess() 处理 APP 下发的控制命令
* 5. 主动上报 / OTA 的网关应答在收到 REPORTCMD_V2 后调用 jbReportAckCheck 清除等待
* ================================================================
*/
#include "jb_product.h"
/* ════════════════════════════════════════════════════════════════
* 全局变量
* ════════════════════════════════════════════════════════════════ */
jb_data_point_t gDevData;
static volatile uint32_t timerMs;
/* ════════════════════════════════════════════════════════════════
* userInit — DP 默认值
* ════════════════════════════════════════════════════════════════ */
void userInit(void)
{
memset(&gDevData, 0, sizeof(jb_data_point_t));
gDevData.power = 0; /* DP0 总开关 0=关 1=开 */
gDevData.spray_switch = 0; /* DP1 喷淋开关 0=关 1=开 */
gDevData.mode = 0; /* MODE_0 (关闭模式) */
gDevData.once_spray_time = 0; /* DP3 单次喷淋时长 */
gDevData.continuous_spray_time = 0; /* DP4 连续喷淋时长 */
gDevData.current_temp = 0.0f; /* DP5 当前温度 (float) */
gDevData.current_humi = 0; /* DP6 当前湿度 */
memset(gDevData.spray_config, 0, 8); /* DP7 喷淋配置 */
gDevData.linkage_delete = 0; /* DP8 联动删除 0=关 1=开 */
memset(gDevData.linkage_config, 0, 20); /* DP9 联动配置 */
gDevData.spray_plan_en = 0; /* DP10 喷淋计划总开关 0=关 1=开 */
memset(gDevData.spray_plan1, 0, 15); /* DP11 喷淋计划1 */
memset(gDevData.time_config2, 0, 15); /* DP12 喷淋计划2 */
memset(gDevData.time_config3, 0, 15); /* DP13 喷淋计划3 */
memset(gDevData.time_config4, 0, 15); /* DP14 喷淋计划4 */
memset(gDevData.time_config5, 0, 15); /* DP15 喷淋计划5 */
memset(gDevData.time_config6, 0, 15); /* DP16 喷淋计划6 */
memset(gDevData.time_config7, 0, 15); /* DP17 喷淋计划7 */
memset(gDevData.run_record, 0, 124); /* DP18 运行记录 */
gDevData.heartbeat = 0; /* DP19 心跳 0=关 1=开 */
gDevData.fault_en = 0; /* DP20 设备故障使能 */
gDevData.fault_code = 0; /* DP21 设备故障 */
gDevData.alarm_en = 0; /* DP22 设备告警使能 */
gDevData.alarm_code = 0; /* DP23 设备告警 */
gDevData.factory_reset = 0; /* DP24 恢复出厂设置 0=关 1=开 */
gDevData.reserva_dp1 = 0; /* DP25 预留DP1 */
gDevData.reserva_dp2 = 0; /* DP26 预留DP2 */
gDevData.reserva_dp3 = 0; /* DP27 预留DP3 */
}
/* ════════════════════════════════════════════════════════════════
* userHandle — 用户数据采集
* 协议层自动检测变化并上报(注意:此处是上报,不是下发控制)
* ════════════════════════════════════════════════════════════════ */
void userHandle(void)
{
/* ── 可上报 DP (RO / RW): 用户数据采集 ── */
// gDevData.power = read_sensor(); /* DP0 总开关 */
// gDevData.spray_switch = read_sensor(); /* DP1 喷淋开关 */
// gDevData.mode = read_sensor(); /* DP2 模式 */
// gDevData.once_spray_time = read_sensor(); /* DP3 单次喷淋时长 */
// gDevData.continuous_spray_time = read_sensor(); /* DP4 连续喷淋时长 */
// memcpy(gDevData.spray_config, sensor_read(), 8); /* DP7 喷淋配置 */
// gDevData.linkage_delete = read_sensor(); /* DP8 联动删除 */
// memcpy(gDevData.linkage_config, sensor_read(), 20); /* DP9 联动配置 */
// gDevData.spray_plan_en = read_sensor(); /* DP10 喷淋计划总开关 */
// memcpy(gDevData.spray_plan1, sensor_read(), 15); /* DP11 喷淋计划1 */
// memcpy(gDevData.time_config2, sensor_read(), 15); /* DP12 喷淋计划2 */
// memcpy(gDevData.time_config3, sensor_read(), 15); /* DP13 喷淋计划3 */
// memcpy(gDevData.time_config4, sensor_read(), 15); /* DP14 喷淋计划4 */
// memcpy(gDevData.time_config5, sensor_read(), 15); /* DP15 喷淋计划5 */
// memcpy(gDevData.time_config6, sensor_read(), 15); /* DP16 喷淋计划6 */
// memcpy(gDevData.time_config7, sensor_read(), 15); /* DP17 喷淋计划7 */
// memcpy(gDevData.run_record, sensor_read(), 124); /* DP18 运行记录 */
// gDevData.fault_en = read_sensor(); /* DP20 设备故障使能 */
// gDevData.fault_code = read_sensor(); /* DP21 设备故障 */
// gDevData.alarm_en = read_sensor(); /* DP22 设备告警使能 */
// gDevData.alarm_code = read_sensor(); /* DP23 设备告警 */
// gDevData.reserva_dp1 = read_sensor(); /* DP25 预留DP1 */
// gDevData.reserva_dp2 = read_sensor(); /* DP26 预留DP2 */
// gDevData.reserva_dp3 = read_sensor(); /* DP27 预留DP3 */
}
/* ════════════════════════════════════════════════════════════════
* jbEventProcess — 0x03 APP 控制事件处理(下行 / DP 赋值方向)
*
* 协议层自动解包 0x03 帧后调用本函数。
* info->dp_ids[] = 被控制的 DP ID 列表
* ctrl 已填入下发的值;复制到 gDevData 并执行动作
* ════════════════════════════════════════════════════════════════ */
int8_t jbEventProcess(jb_event_info_t *info, jb_data_point_t *ctrl)
{
if (!info || !ctrl)
{
return -1;
}
for (uint8_t i = 0; i < info->count; i++)
{
switch (info->dp_ids[i])
{
/* ── DP0 总开关 (bool) ── */
case DP_ID_POWER:
if (ctrl->power)
{
gDevData.power = 1;
// TODO: 开 — 执行动作
}
else
{
gDevData.power = 0;
// TODO: 关 — 执行动作
}
break;
/* ── DP1 喷淋开关 (bool) ── */
case DP_ID_SPRAY_SWITCH:
if (ctrl->spray_switch)
{
gDevData.spray_switch = 1;
// TODO: 开 — 执行动作
}
else
{
gDevData.spray_switch = 0;
// TODO: 关 — 执行动作
}
break;
/* ── DP2 模式 (enum) ── */
case DP_ID_MODE:
gDevData.mode = ctrl->mode;
switch (ctrl->mode)
{
case MODE_0: /* 关闭模式 */
// TODO: 处理 关闭模式
break;
case MODE_1: /* 单次喷淋 */
// TODO: 处理 单次喷淋
break;
case MODE_2: /* 连续喷淋 */
// TODO: 处理 连续喷淋
break;
default:
break;
}
break;
/* ── DP3 单次喷淋时长 (uint8) ── */
case DP_ID_ONCE_SPRAY_TIME:
gDevData.once_spray_time = ctrl->once_spray_time;
// TODO: 根据 ctrl->once_spray_time 执行动作
break;
/* ── DP4 连续喷淋时长 (uint8) ── */
case DP_ID_CONTINUOUS_SPRAY_TIME:
gDevData.continuous_spray_time = ctrl->continuous_spray_time;
// TODO: 根据 ctrl->continuous_spray_time 执行动作
break;
/* ── DP5 当前温度 (float, scale=0.1) ── */
case DP_ID_CURRENT_TEMP:
gDevData.current_temp = ctrl->current_temp;
// TODO: 根据 ctrl->current_temp 执行动作 (已是浮点物理量)
break;
/* ── DP6 当前湿度 (uint8) ── */
case DP_ID_CURRENT_HUMI:
gDevData.current_humi = ctrl->current_humi;
// TODO: 根据 ctrl->current_humi 执行动作
break;
/* ── DP7 喷淋配置 (raw) ── */
case DP_ID_SPRAY_CONFIG:
memcpy(gDevData.spray_config, ctrl->spray_config, 8);
// TODO: 根据 gDevData.spray_config 执行动作 (长度 8 字节)
break;
/* ── DP8 联动删除 (bool) ── */
case DP_ID_LINKAGE_DELETE:
if (ctrl->linkage_delete)
{
gDevData.linkage_delete = 1;
// TODO: 开 — 执行动作
}
else
{
gDevData.linkage_delete = 0;
// TODO: 关 — 执行动作
}
break;
/* ── DP9 联动配置 (raw) ── */
case DP_ID_LINKAGE_CONFIG:
memcpy(gDevData.linkage_config, ctrl->linkage_config, 20);
// TODO: 根据 gDevData.linkage_config 执行动作 (长度 20 字节)
break;
/* ── DP10 喷淋计划总开关 (bool) ── */
case DP_ID_SPRAY_PLAN_EN:
if (ctrl->spray_plan_en)
{
gDevData.spray_plan_en = 1;
// TODO: 开 — 执行动作
}
else
{
gDevData.spray_plan_en = 0;
// TODO: 关 — 执行动作
}
break;
/* ── DP11 喷淋计划1 (raw) ── */
case DP_ID_SPRAY_PLAN1:
memcpy(gDevData.spray_plan1, ctrl->spray_plan1, 15);
// TODO: 根据 gDevData.spray_plan1 执行动作 (长度 15 字节)
break;
/* ── DP12 喷淋计划2 (raw) ── */
case DP_ID_TIME_CONFIG2:
memcpy(gDevData.time_config2, ctrl->time_config2, 15);
// TODO: 根据 gDevData.time_config2 执行动作 (长度 15 字节)
break;
/* ── DP13 喷淋计划3 (raw) ── */
case DP_ID_TIME_CONFIG3:
memcpy(gDevData.time_config3, ctrl->time_config3, 15);
// TODO: 根据 gDevData.time_config3 执行动作 (长度 15 字节)
break;
/* ── DP14 喷淋计划4 (raw) ── */
case DP_ID_TIME_CONFIG4:
memcpy(gDevData.time_config4, ctrl->time_config4, 15);
// TODO: 根据 gDevData.time_config4 执行动作 (长度 15 字节)
break;
/* ── DP15 喷淋计划5 (raw) ── */
case DP_ID_TIME_CONFIG5:
memcpy(gDevData.time_config5, ctrl->time_config5, 15);
// TODO: 根据 gDevData.time_config5 执行动作 (长度 15 字节)
break;
/* ── DP16 喷淋计划6 (raw) ── */
case DP_ID_TIME_CONFIG6:
memcpy(gDevData.time_config6, ctrl->time_config6, 15);
// TODO: 根据 gDevData.time_config6 执行动作 (长度 15 字节)
break;
/* ── DP17 喷淋计划7 (raw) ── */
case DP_ID_TIME_CONFIG7:
memcpy(gDevData.time_config7, ctrl->time_config7, 15);
// TODO: 根据 gDevData.time_config7 执行动作 (长度 15 字节)
break;
/* ── DP19 心跳 (bool) ── */
case DP_ID_HEARTBEAT:
if (ctrl->heartbeat)
{
gDevData.heartbeat = 1;
// TODO: 开 — 执行动作
}
else
{
gDevData.heartbeat = 0;
// TODO: 关 — 执行动作
}
break;
/* ── DP20 设备故障使能 (uint8) ── */
case DP_ID_FAULT_EN:
gDevData.fault_en = ctrl->fault_en;
// TODO: 根据 ctrl->fault_en 执行动作
break;
/* ── DP22 设备告警使能 (uint8) ── */
case DP_ID_ALARM_EN:
gDevData.alarm_en = ctrl->alarm_en;
// TODO: 根据 ctrl->alarm_en 执行动作
break;
/* ── DP24 恢复出厂设置 (bool) ── */
case DP_ID_FACTORY_RESET:
if (ctrl->factory_reset)
{
gDevData.factory_reset = 1;
// TODO: 开 — 执行动作
}
else
{
gDevData.factory_reset = 0;
// TODO: 关 — 执行动作
}
break;
/* ── DP25 预留DP1 (uint32) ── */
case DP_ID_RESERVA_DP1:
gDevData.reserva_dp1 = ctrl->reserva_dp1;
// TODO: 根据 ctrl->reserva_dp1 执行动作
break;
/* ── DP26 预留DP2 (uint32) ── */
case DP_ID_RESERVA_DP2:
gDevData.reserva_dp2 = ctrl->reserva_dp2;
// TODO: 根据 ctrl->reserva_dp2 执行动作
break;
/* ── DP27 预留DP3 (uint32) ── */
case DP_ID_RESERVA_DP3:
gDevData.reserva_dp3 = ctrl->reserva_dp3;
// TODO: 根据 ctrl->reserva_dp3 执行动作
break;
default:
break;
}
}
return 0;
}
/* 0x30 OTA 升级请求
* 返回 0=接受升级(协议层应答 JB_OK + MaxDataLen
* 非 0=拒绝,返回值即错误码(JB_OTA_*)
*
* ⚠ SOC 侧 OTA 尚未实现:当前仅应答,不执行任何升级动作。 */
int8_t jbOnOtaNotify(uint32_t fwVersion, uint32_t fwLength, uint32_t fwCrc32)
{
(void)fwVersion; (void)fwLength; (void)fwCrc32;
// TODO: 检查 Flash 空间与版本,决定是否接收升级
// 允许: 返回 JB_OK(协议层应答 JB_OK + MaxDataLen
// 拒绝: 返回对应 JB_OTA_* 错误码(如 JB_OTA_VER_LOW / JB_OTA_SPACE_ERR
return JB_OK;
}
/* 0x32 OTA 数据(含分片序号)*/
void jbOnOtaData(const uint8_t *data, uint16_t len,
uint16_t shardIdx, uint16_t totalShards)
{
(void)data; (void)len; (void)shardIdx; (void)totalShards;
// TODO: 写入 Flash,累计 CRC32
// 全部数据接收完成后调用 jbSendOtaResult(JB_OK, mcuVersion)
}
/* 0x36 / 0x38 停止 OTA */
void jbOnOtaStop(void)
{
// TODO: 终止 OTA,释放资源
}
/* 任意 MCU→BLE 请求的 ACK 回调(cmd 标识是哪条请求的应答,result 为结果码)
- SOC 仅保留 OTA 主动请求应答: OTA完成 0x35 / 停止 0x39
- 可在本回调中设置"XX 完成/失败"标志,供主循环判断"确认成功才继续" */
void jbOnAck(uint8_t cmd, uint8_t result)
{
(void)cmd;
(void)result;
// TODO: switch(cmd){ case CMD_OTA_COMPLETE_ACK: gOtaDone = (result==JB_OK); break; case CMD_OTA_STOP_MCU_ACK: ... }
}
/* ════════════════════════════════════════════════════════════════
* 硬件抽象(按实际平台实现)
* ════════════════════════════════════════════════════════════════ */
/* ── 定时器 ── */
void jbTimerIrq(void)
{
timerMs++;
} /* 在 1ms 中断中调用本函数 */
uint32_t jbGetTimerCount(void)
{
return timerMs;
}
+55
View File
@@ -0,0 +1,55 @@
/* ================================================================
* jb_product.h — 用户层头文件(自动生成)
* 设备: 喷淋器 | 生成时间: 2026-09-09 10:22:58
*
* 声明用户需实现的函数。数据结构定义见 jb_protocol.h
* ================================================================
*/
#ifndef _JB_PRODUCT_H
#define _JB_PRODUCT_H
#include "jb_protocol.h"
/* ════════════════════════════════════════════════════════════════
* 硬件配置(SOC SDK 已提供定时器,无需 UART 波特率配置)
* ════════════════════════════════════════════════════════════════ */
#define TIMER_PERIOD_MS 1
/* ════════════════════════════════════════════════════════════════
* 版本管理
* ════════════════════════════════════════════════════════════════ */
/* MCU software version: Vmajor.minor.patch */
#define JB_MCU_SW_VERSION_MAJOR 1
#define JB_MCU_SW_VERSION_MINOR 0
#define JB_MCU_SW_VERSION_PATCH 0
/* MCU hardware version: Vmajor.minor.patch */
#define JB_MCU_HW_VERSION_MAJOR 1
#define JB_MCU_HW_VERSION_MINOR 0
#define JB_MCU_HW_VERSION_PATCH 0
/* ════════════════════════════════════════════════════════════════
* 用户 API
* ════════════════════════════════════════════════════════════════ */
/* 全局设备数据 — 协议层直接读写该变量 */
extern jb_data_point_t gDevData;
/* ==================== 用户必须实现 ============================== */
void userInit(void); /* DP 默认值与外设初始化 */
void userHandle(void); /* 用户数据采集 */
void jbTimerIrq(void); /* Call from 1ms timer ISR */
/* =========== 协议回调(声明见 jb_protocol.h================== */
/* int8_t jbEventProcess(...); // 0x03 控制事件 */
/* int8_t jbOnOtaNotify(...); // 0x30 OTA 请求 */
/* void jbOnOtaData(...); // 0x32 OTA 数据 */
/* void jbOnOtaStop(); // 0x36/0x38 停止 OTA */
/* void jbOnAck(...); // 任意请求 ACK(结果) */
/* ============= 主动请求(声明见 jb_protocol.h================ */
/* int32_t jbNotifyOtaStop(); // 0x38 通知 BLE 停止 OTA */
/* int32_t jbSendOtaResult(...); // 0x34 OTA 结果 */
#endif /* _JB_PRODUCT_H */
File diff suppressed because it is too large Load Diff
+308
View File
@@ -0,0 +1,308 @@
/* ================================================================
* jb_protocol.h — 见宝 IOT 协议层(自动生成)
* 设备: 喷淋器 | DP 数: 28 | Bitmap: 4B
* 协议版本: V1.0 | 生成时间: 2026-09-09 10:22:58
*
* 帧格式: [55 AA] [LEN_H LEN_L] [CMD] [SN] [payload...] [CKSUM]
* LEN = CMD(1) + SN(1) + payload + CKSUM(1) = payload + 3
* CKSUM = sum(LEN_H .. payload_last) & 0xFF
* Bitmap = 每个 DP 占 1 bitbit 序号 = DP ID0 起始)
* Values = 按 bitmap 置位顺序排列,每个 DP 占完整 byte_length
* ================================================================
*/
#ifndef _JB_PROTOCOL_H
#define _JB_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include <string.h>
/* ════════════════════════════════════════════════════════════════
* 协议常量
* ════════════════════════════════════════════════════════════════ */
#define PKT_HEAD_0 0x55
#define PKT_HEAD_1 0xAA
#define MAX_PACKAGE_LEN 128
#define JB_OTA_MAX_PAYLOAD 96 /* OTA 单包 Payload 上限(Byte); 须 <= MAX_PACKAGE_LEN - 11(0x32 帧开销) */
#define DP_COUNT 28
#define DP_BITMAP_SIZE 4
#define SEND_MAX_TIME 2500 /* ACK 重传超时(ms)BLE Indication往返常需数百ms~1s,过短会误重传导致双应答 */
#define SEND_MAX_NUM 3 /* 最大重传次数 */
#define REPORT_DEBOUNCE 2000 /* 变化上报防抖时间(ms) */
#define REPORT_PERIOD 600000 /* 定时全量上报周期(ms) */
/* Device identity: 取自 Excel 设备信息表的 ProdtCode / productCode。
* JB_CATEGORY_CODE: 必须 4 字符 ASCII,供 BLE 广播 prodcode 使用
* JB_PRODUCT_CODE : 必须 6 字符 ASCII,供 BLE 广播 pcode 使用
* 模板未填时回退占位 XXXX / XXXXXX(仍需用户修改)。
*/
#define JB_PROTOCOL_VERSION 0x0100 /* V1.0 */
#define JB_CATEGORY_CODE "CBR2"
#define JB_PRODUCT_CODE "PRCBR2"
#define JB_DEVICE_SN 0x00
#define JB_DEVICE_CAPABILITY 0ULL
/* ════════════════════════════════════════════════════════════════
* 命令码(见《SOC方案接入协议通讯文档》)
* ════════════════════════════════════════════════════════════════ */
typedef enum
{
/* ── APP-BLE 数据(6) ── */
CMD_CONTROL = 0x03, /* APP/BLE → MCU: 下发控制 */
CMD_CONTROL_ACK = 0x04, /* MCU → APP/BLE: 控制应答 */
CMD_READ = 0x05, /* APP/BLE → MCU: 读取请求 */
CMD_READ_ACK = 0x06, /* MCU → APP/BLE: 读取应答 */
CMD_REPORT = 0x07, /* MCU → APP/BLE: 主动上报 */
CMD_REPORT_ACK = 0x08, /* APP/BLE → MCU: 上报应答 */
/* ── OTA(10) ── */
CMD_OTA_NOTIFY = 0x30, /* BLE → MCU: OTA 升级请求 */
CMD_OTA_NOTIFY_ACK = 0x31, /* MCU → BLE: OTA 应答(含MaxLen) */
CMD_OTA_DATA = 0x32, /* BLE → MCU: OTA 数据 */
CMD_OTA_DATA_ACK = 0x33, /* MCU → BLE: OTA 数据应答 */
CMD_OTA_COMPLETE = 0x34, /* MCU → BLE: OTA 完成 */
CMD_OTA_COMPLETE_ACK = 0x35, /* BLE → MCU: OTA 完成应答 */
CMD_OTA_STOP_BLE = 0x36, /* BLE → MCU: 停止 OTA */
CMD_OTA_STOP_BLE_ACK = 0x37, /* MCU → BLE: 停止应答 */
CMD_OTA_STOP_MCU = 0x38, /* MCU → BLE: 通知停止 OTA */
CMD_OTA_STOP_MCU_ACK = 0x39, /* BLE → MCU: 停止应答 */
} jb_cmd_t;
/* ════════════════════════════════════════════════════════════════
* 结果码
* ════════════════════════════════════════════════════════════════ */
typedef enum
{
JB_OK = 0x00,
JB_PARAM_ERR = 0x01,
JB_BUSY = 0x02,
JB_NOT_SUPPORT = 0x03,
JB_CRC_ERR = 0x04,
JB_FAIL = 0x05,
/* ── OTA 专用错误码 ── */
JB_OTA_NO_NEED = 0x20, /* 无需升级(版本一致) */
JB_OTA_VER_LOW = 0x21, /* OTA 版本低于当前版本 */
JB_OTA_SPACE_ERR = 0x22, /* Flash 空间不足 */
JB_OTA_STATE_ERR = 0x23, /* OTA 状态错误 */
JB_OTA_FILE_ERR = 0x24, /* OTA 文件检验失败 */
JB_OTA_FAIL = 0x25, /* 升级失败 */
} jb_result_t;
/* ════════════════════════════════════════════════════════════════
* BLE 工作状态位 (0x14)
* ════════════════════════════════════════════════════════════════ */
#define WS_CONNECTING (1 << 0) /* 配网中 */
#define WS_CONFIGURED (1 << 1) /* 已配网 */
#define WS_RECONNECTING (1 << 2) /* 断线重连中 */
#define WS_CLOUD_CONNECTED (1 << 3) /* 已连接到云 */
#define WS_APP_ONLINE (1 << 4) /* App 在线 */
#define WS_APP_DIRECT (1 << 5) /* App 直连 */
#define WS_OTA_UPGRADING (1 << 6) /* 模组 OTA 升级中 */
#define WS_RESERVED (1 << 7) /* 保留 */
/* ════════════════════════════════════════════════════════════════
* 设备能力位图 (0x02 Capability Bitmap, 8B 大端)
* ════════════════════════════════════════════════════════════════ */
#define CAP_BLE_OTA (1ULL << 0) /* BLE OTA */
#define CAP_MCU_OTA (1ULL << 1) /* MCU OTA */
#define CAP_APP_DIRECT (1ULL << 2) /* APP 直连 BLE */
#define CAP_IPC_GATEWAY (1ULL << 3) /* IPC 网关连接 */
#define CAP_PRODUCTION (1ULL << 4) /* 产测模式 */
#define CAP_PARAM_CFG (1ULL << 5) /* 参数配置 */
#define CAP_LOG (1ULL << 6) /* 日志功能 */
/* ════════════════════════════════════════════════════════════════
* DP ID 枚举(从 Excel 自动生成)
* ════════════════════════════════════════════════════════════════ */
typedef enum
{
DP_ID_POWER = 0, /* 总开关 (bool, RW) */
DP_ID_SPRAY_SWITCH = 1, /* 喷淋开关 (bool, RW) */
DP_ID_MODE = 2, /* 模式 (enum, RW) */
DP_ID_ONCE_SPRAY_TIME = 3, /* 单次喷淋时长 (uint8, RW) */
DP_ID_CONTINUOUS_SPRAY_TIME = 4, /* 连续喷淋时长 (uint8, RW) */
DP_ID_CURRENT_TEMP = 5, /* 当前温度 (float, WO) */
DP_ID_CURRENT_HUMI = 6, /* 当前湿度 (uint8, WO) */
DP_ID_SPRAY_CONFIG = 7, /* 喷淋配置 (raw, RW) */
DP_ID_LINKAGE_DELETE = 8, /* 联动删除 (bool, RW) */
DP_ID_LINKAGE_CONFIG = 9, /* 联动配置 (raw, RW) */
DP_ID_SPRAY_PLAN_EN = 10, /* 喷淋计划总开关 (bool, RW) */
DP_ID_SPRAY_PLAN1 = 11, /* 喷淋计划1 (raw, RW) */
DP_ID_TIME_CONFIG2 = 12, /* 喷淋计划2 (raw, RW) */
DP_ID_TIME_CONFIG3 = 13, /* 喷淋计划3 (raw, RW) */
DP_ID_TIME_CONFIG4 = 14, /* 喷淋计划4 (raw, RW) */
DP_ID_TIME_CONFIG5 = 15, /* 喷淋计划5 (raw, RW) */
DP_ID_TIME_CONFIG6 = 16, /* 喷淋计划6 (raw, RW) */
DP_ID_TIME_CONFIG7 = 17, /* 喷淋计划7 (raw, RW) */
DP_ID_RUN_RECORD = 18, /* 运行记录 (raw, RO) */
DP_ID_HEARTBEAT = 19, /* 心跳 (bool, WO) */
DP_ID_FAULT_EN = 20, /* 设备故障使能 (uint8, RW) */
DP_ID_FAULT_CODE = 21, /* 设备故障 (uint8, RO) */
DP_ID_ALARM_EN = 22, /* 设备告警使能 (uint8, RW) */
DP_ID_ALARM_CODE = 23, /* 设备告警 (uint8, RO) */
DP_ID_FACTORY_RESET = 24, /* 恢复出厂设置 (bool, WO) */
DP_ID_RESERVA_DP1 = 25, /* 预留DP1 (uint32, RW) */
DP_ID_RESERVA_DP2 = 26, /* 预留DP2 (uint32, RW) */
DP_ID_RESERVA_DP3 = 27, /* 预留DP3 (uint32, RW) */
DP_ID_MAX
} dp_id_t;
/* DP 数据长度(字节) */
#define DP_LEN_POWER 1
#define DP_LEN_SPRAY_SWITCH 1
#define DP_LEN_MODE 1
#define DP_LEN_ONCE_SPRAY_TIME 1
#define DP_LEN_CONTINUOUS_SPRAY_TIME 1
#define DP_LEN_CURRENT_TEMP 2
#define DP_LEN_CURRENT_HUMI 1
#define DP_LEN_SPRAY_CONFIG 8
#define DP_LEN_LINKAGE_DELETE 1
#define DP_LEN_LINKAGE_CONFIG 20
#define DP_LEN_SPRAY_PLAN_EN 1
#define DP_LEN_SPRAY_PLAN1 15
#define DP_LEN_TIME_CONFIG2 15
#define DP_LEN_TIME_CONFIG3 15
#define DP_LEN_TIME_CONFIG4 15
#define DP_LEN_TIME_CONFIG5 15
#define DP_LEN_TIME_CONFIG6 15
#define DP_LEN_TIME_CONFIG7 15
#define DP_LEN_RUN_RECORD 124
#define DP_LEN_HEARTBEAT 1
#define DP_LEN_FAULT_EN 1
#define DP_LEN_FAULT_CODE 1
#define DP_LEN_ALARM_EN 1
#define DP_LEN_ALARM_CODE 1
#define DP_LEN_FACTORY_RESET 1
#define DP_LEN_RESERVA_DP1 4
#define DP_LEN_RESERVA_DP2 4
#define DP_LEN_RESERVA_DP3 4
/* ════════════════════════════════════════════════════════════════
* DP 枚举值定义
* ════════════════════════════════════════════════════════════════ */
/* 模式 */
typedef enum
{
MODE_0 = 0, /* 关闭模式 */
MODE_1 = 1, /* 单次喷淋 */
MODE_2 = 2, /* 连续喷淋 */
} MODE_t;
/* ════════════════════════════════════════════════════════════════
* 数据结构
* ════════════════════════════════════════════════════════════════ */
/* 数据点 — 所有 DP 的当前值 */
typedef struct
{
uint8_t power; /* DP0 总开关 */
uint8_t spray_switch; /* DP1 喷淋开关 */
uint8_t mode; /* DP2 模式 */
uint8_t once_spray_time;/* DP3 单次喷淋时长 */
uint8_t continuous_spray_time;/* DP4 连续喷淋时长 */
float current_temp; /* DP5 当前温度 (float, scale=0.1) */
uint8_t current_humi; /* DP6 当前湿度 */
uint8_t spray_config[8];/* DP7 喷淋配置 */
uint8_t linkage_delete;/* DP8 联动删除 */
uint8_t linkage_config[20];/* DP9 联动配置 */
uint8_t spray_plan_en;/* DP10 喷淋计划总开关 */
uint8_t spray_plan1[15];/* DP11 喷淋计划1 */
uint8_t time_config2[15];/* DP12 喷淋计划2 */
uint8_t time_config3[15];/* DP13 喷淋计划3 */
uint8_t time_config4[15];/* DP14 喷淋计划4 */
uint8_t time_config5[15];/* DP15 喷淋计划5 */
uint8_t time_config6[15];/* DP16 喷淋计划6 */
uint8_t time_config7[15];/* DP17 喷淋计划7 */
uint8_t run_record[124];/* DP18 运行记录 */
uint8_t heartbeat; /* DP19 心跳 */
uint8_t fault_en; /* DP20 设备故障使能 */
uint8_t fault_code; /* DP21 设备故障 */
uint8_t alarm_en; /* DP22 设备告警使能 */
uint8_t alarm_code; /* DP23 设备告警 */
uint8_t factory_reset;/* DP24 恢复出厂设置 */
uint32_t reserva_dp1; /* DP25 预留DP1 */
uint32_t reserva_dp2; /* DP26 预留DP2 */
uint32_t reserva_dp3; /* DP27 预留DP3 */
} jb_data_point_t;
/* 控制事件信息 */
typedef struct
{
uint8_t count;
uint8_t dp_ids[DP_ID_MAX];
} jb_event_info_t;
/* ACK 等待 / 重传管理器 */
typedef struct
{
uint8_t active; /* 是否有等待中的请求 */
uint8_t sn; /* 帧序列号 */
uint8_t retry;
uint8_t buf[MAX_PACKAGE_LEN];
uint16_t len;
uint32_t sendTime;
} jb_wait_ack_t;
/* 协议全局状态 */
typedef struct
{
uint8_t sn; /* 设备 SN 计数器 */
uint8_t rxBuf[MAX_PACKAGE_LEN];
jb_wait_ack_t waitAck; /* ACK 重传管理器 */
jb_data_point_t lastData; /* 上次上报快照 */
uint32_t lastReportTime; /* 上次上报时刻 */
uint32_t lastChangeTime; /* 上次变化上报时刻 */
} jb_protocol_t;
/* ════════════════════════════════════════════════════════════════
* 全局实例
* ════════════════════════════════════════════════════════════════ */
extern jb_protocol_t jbProtocol;
/* ════════════════════════════════════════════════════════════════
* 协议层 API(自动生成)
* ════════════════════════════════════════════════════════════════ */
void jbInit(void);
int32_t jbPutData(uint8_t *buf, uint32_t len);
int32_t jbNotifyOtaStop(void);
int32_t jbSendOtaResult(uint8_t result, const uint8_t *mcuVersion);
int32_t jbProtocolHandle(jb_data_point_t *data);
/*
* 网关应答确认(主动上报 / OTA 共用,REPORTCMD_V2,非 55AA
* cmd: ble_proto 包 cmd
* gateway_int_cnt: gateway int 个数
* gateway_int0: gateway_int[0]
* 成功条件: cmd==0 && gateway_int_cnt==1 && gateway_int0==0
* 返回: 1=成功并清除等待; 0=未命中/条件不符
*/
int8_t jbReportAckCheck(uint16_t cmd, uint8_t gateway_int_cnt, int32_t gateway_int0);
/* ════════════════════════════════════════════════════════════════
* 硬件抽象(用户实现)
* ════════════════════════════════════════════════════════════════ */
uint32_t jbGetTimerCount(void); /* ms 计数器(定时器由 SOC SDK 提供) */
/* 发送接口:经 SOC SDK 提供的 BLE 发送封装(由用户/SDK 实现,非本生成代码范围)*/
extern void ble_send_data(uint8_t *data, uint16_t len);
/* ════════════════════════════════════════════════════════════════
* 用户回调(用户实现)
* ════════════════════════════════════════════════════════════════ */
/* 0x03 APP 下发控制事件 */
int8_t jbEventProcess(jb_event_info_t *info, jb_data_point_t *data);
/* BLE → MCU 事件回调 */
int8_t jbOnOtaNotify(uint32_t fwVersion, uint32_t fwLength, uint32_t fwCrc32); /* 0x30, 返回0=接受,非0=拒绝码 */
void jbOnOtaData(const uint8_t *data, uint16_t len,
uint16_t shardIdx, uint16_t totalShards); /* 0x32 */
void jbOnOtaStop(void); /* 0x36 / 0x38 停止 */
/* MCU → BLE 应答回调(收到 BLE 应答时触发)*/
void jbOnAck(uint8_t cmd, uint8_t result); /* 任意请求 ACK(结果) */
#endif /* _JB_PROTOCOL_H */
+69
View File
@@ -0,0 +1,69 @@
/* ================================================================
* jb_common.c — 工具函数实现
* ================================================================
*/
#include "jb_common.h"
/* ════════════════════════════════════════════════════════════════
* 校验和
* ════════════════════════════════════════════════════════════════ */
uint8_t jbChecksum(const uint8_t *frame, uint16_t totalLen)
{
if (!frame || totalLen < 4)
{
return 0;
}
uint16_t sum = 0;
/* 从 LEN_H(buf[2]) 累加到最后一个 payload 字节(buf[totalLen-2]) */
for (uint16_t i = 2; i < totalLen - 1; i++)
{
sum += frame[i];
}
return (uint8_t)(sum & 0xFF);
}
/* ════════════════════════════════════════════════════════════════
* 大端序读写
* ════════════════════════════════════════════════════════════════ */
uint16_t jbReadU16BE(const uint8_t *buf)
{
if (!buf)
{
return 0;
}
return ((uint16_t)buf[0] << 8) | buf[1];
}
uint32_t jbReadU32BE(const uint8_t *buf)
{
if (!buf)
{
return 0;
}
return ((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| buf[3];
}
void jbWriteU16BE(uint8_t *buf, uint16_t val)
{
if (!buf)
{
return;
}
buf[0] = (uint8_t)(val >> 8);
buf[1] = (uint8_t)(val & 0xFF);
}
void jbWriteU32BE(uint8_t *buf, uint32_t val)
{
if (!buf)
{
return;
}
buf[0] = (uint8_t)(val >> 24);
buf[1] = (uint8_t)(val >> 16);
buf[2] = (uint8_t)(val >> 8);
buf[3] = (uint8_t)(val & 0xFF);
}
+37
View File
@@ -0,0 +1,37 @@
/* ================================================================
* jb_common.h — 工具函数(校验和、大端序转换)
*
* 说明: 见宝协议采用大端序(Big-Endian)。
* 多字节值(uint16/uint32)按高位在前传输。
* ================================================================
*/
#ifndef _JB_COMMON_H
#define _JB_COMMON_H
#include <stdint.h>
#include <stddef.h>
/* ════════════════════════════════════════════════════════════════
* 校验和
* sum(LEN_H, LEN_L, CMD, SN, ...payload_last) & 0xFF
* buf[0]=55, buf[1]=AA,累加范围从 buf[2] 到 buf[totalLen-2]
* ════════════════════════════════════════════════════════════════ */
uint8_t jbChecksum(const uint8_t *frame, uint16_t totalLen);
/* ════════════════════════════════════════════════════════════════
* 大端序转换
* ════════════════════════════════════════════════════════════════ */
/* 从字节数组读取 uint16(大端序)*/
uint16_t jbReadU16BE(const uint8_t *buf);
/* 从字节数组读取 uint32(大端序)*/
uint32_t jbReadU32BE(const uint8_t *buf);
/* 将 uint16 写入字节数组(大端序)*/
void jbWriteU16BE(uint8_t *buf, uint16_t val);
/* 将 uint32 写入字节数组(大端序)*/
void jbWriteU32BE(uint8_t *buf, uint32_t val);
#endif /* _JB_COMMON_H */
+75
View File
@@ -0,0 +1,75 @@
/* ================================================================
* jb_ringbuffer.c — 环形缓冲区实现
* ================================================================
*/
#include "jb_ringbuffer.h"
/* ── 初始化 ── */
void jbRbInit(jb_ringbuffer_t *rb)
{
if (!rb)
{
return;
}
rb->write = rb->read = rb->count = 0;
}
/* ── 压入一个字节 ── */
void jbRbPush(jb_ringbuffer_t *rb, uint8_t byte)
{
if (!rb)
{
return;
}
if (rb->count >= JB_RB_CAPACITY)
{
return; /* 已满 — 丢弃 */
}
rb->buf[rb->write] = byte;
rb->write = (rb->write + 1) % JB_RB_CAPACITY;
rb->count++;
}
/* ── 弹出一个字节 ── */
uint8_t jbRbPop(jb_ringbuffer_t *rb)
{
if (!rb || rb->count == 0)
{
return 0;
}
uint8_t byte = rb->buf[rb->read];
rb->read = (rb->read + 1) % JB_RB_CAPACITY;
rb->count--;
return byte;
}
/* ── 查看指定偏移字节(不消费)── */
uint8_t jbRbPeek(const jb_ringbuffer_t *rb, uint16_t offset)
{
if (!rb || offset >= rb->count)
{
return 0;
}
uint16_t idx = (rb->read + offset) % JB_RB_CAPACITY;
return rb->buf[idx];
}
/* ── 可读字节数 ── */
uint16_t jbRbAvailable(const jb_ringbuffer_t *rb)
{
if (!rb)
{
return 0;
}
return rb->count;
}
/* ── 清空缓冲区 ── */
void jbRbClear(jb_ringbuffer_t *rb)
{
if (!rb)
{
return;
}
rb->write = rb->read = rb->count = 0;
}
+30
View File
@@ -0,0 +1,30 @@
/* ================================================================
* jb_ringbuffer.h — 环形缓冲区(UART 接收)
* ================================================================
*/
#ifndef _JB_RINGBUFFER_H
#define _JB_RINGBUFFER_H
#include <stdint.h>
#include <stddef.h>
/* 缓冲区配置 */
#define JB_RB_CAPACITY 256 /* 缓冲区容量(2 的幂可优化取模运算)*/
/* 环形缓冲区实例 */
typedef struct
{
uint8_t buf[JB_RB_CAPACITY];
uint16_t write; /* 写索引 */
uint16_t read; /* 读索引 */
uint16_t count; /* 已用字节数 */
} jb_ringbuffer_t;
void jbRbInit(jb_ringbuffer_t *rb);
void jbRbPush(jb_ringbuffer_t *rb, uint8_t byte);
uint8_t jbRbPop(jb_ringbuffer_t *rb);
uint8_t jbRbPeek(const jb_ringbuffer_t *rb, uint16_t offset);
uint16_t jbRbAvailable(const jb_ringbuffer_t *rb);
void jbRbClear(jb_ringbuffer_t *rb);
#endif /* _JB_RINGBUFFER_H */
+49
View File
@@ -0,0 +1,49 @@
#include "system/includes.h"
#include "app_config.h"
#include "app_main.h"
#include "app_task.h"
#include "user_cfg.h"
#include "vm.h"
#include "sys_time.h"
#include "jb_protocol.h"
#include "jb_product.h"
#include "jb_ringbuffer.h"
#include "jb_common.h"
#include "usr_le_product.h"
/* 向 usr_le_code 库提供产品身份(换产品只改 jb_protocol.h 宏即可) */
const uint8_t g_usr_le_prodcode[USR_LE_PRODCODE_LEN] = {
JB_CATEGORY_CODE[0], JB_CATEGORY_CODE[1],
JB_CATEGORY_CODE[2], JB_CATEGORY_CODE[3]
};
const uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN] = {
JB_PRODUCT_CODE[0], JB_PRODUCT_CODE[1], JB_PRODUCT_CODE[2],
JB_PRODUCT_CODE[3], JB_PRODUCT_CODE[4], JB_PRODUCT_CODE[5]
};
void usr_timer_1_ms();
static int jb_timer_id=0;
void usr_jb_init()
{
jbInit();
userInit();
if(jb_timer_id==0)jb_timer_id = sys_s_hi_timer_add(NULL, usr_timer_1_ms, TIMER_PERIOD_MS);
}
void usr_timer_1_ms()
{
jbTimerIrq();
}
void usr_jb_le_recieve_data(u8* data,u16 len)
{
jbPutData(data,len);
}
void usr_timer_loop()///500ms
{
userHandle();
jbProtocolHandle(&gDevData);
}