Vibecoding尝鲜之-使用Cursor完成MQTT开发(一)
最近对接一个政府部门的MQTT业务开发需求,本案例在我原本手动开发的需求上进行功能的添加,现在使用Cursor来完成功能需求,本文使用Cursor来独立完成整体的框架开发和具体的业务需求,我将仅提需求给Cursor,其他的代码功能交给Cursor,要求他能够完成像样的一个功能。
原本的业务要求是:业务人员根据项目现场的收资(点表信息)情况,通过平台的后台对项目现场的设备进行物理模型(储能设备)建立。物理模型建立完毕生成网关的唯一标识关联编码dcode以及接入MQTT 服务器的用户名、密码和证书,由业务人员线下分配给现场接入网关,建立后将设备信息上送至客户的MQTT服务器端。
涉及到MQTT订阅和双向认证的功能部分,现梳理整个开发的逻辑链路。
一:MQTT连接
1. 地址 IP:储能云端URL:10.10.0.109
普通物联卡和省综 APN 卡地址不同, 请联系平台人员获取
2. 端口 Port:储能云端URL:18603
请联系平台人员获取
3. 用户名密码:MQTT 用户名:yfyjs,MQTT 密码:Fs1w3#f%sp8M
业务人员分配(线下)
4. Client_ID:
填写业务人员分配的网关关联编码 dcode(对应储能:设备编号ESS Device ID)
5. 加密证书:
SSL 加密(双向认证) , 证书线下获取。(数据信息:升级mTLS双向认证文件)
6. 发布和订阅主题
MQTT主题类型+主题后缀名:
| 发布:jssz/puc/{tag}/{dcode}/ register |
| 订阅:jssz/puc/{tag}/{dcode}/register/ack |
tag:为版本号,目前为 v2.0。dcode:物联平台分配的网关关联编码

|
云平台厂家(重启) |
FB01_MQTT+TLS(JN) |
|
储能云端URL |
厂家提供 |
|
TLS认证等级 |
双向认证 |
|
MQTT 用户名 |
Mqtt_Test1 |
|
MQTT 密码 |
123456 |
MQTT主题类型组成:MQTT主题类型 + 后缀
pMqtt->szSelfTopic + szTopic:jssz/puc/{tag}/{dcode}/ + register。用于发布主题。
MQTT订阅:MQTT主题类型 + 后缀
pMqtt->szSelfTopic + szTopic:jssz/puc/{tag}/{dcode}/ + register/ack。用于订阅主题。
|
MQTT主题类型 |
|
MQTT版本 |
3-1-1 |
|
QOS |
0 |
发布函数:
rc = MQTTAsync_sendMessage(client, szSubTopicBuffer, &pubmsg, &opts)) != MQTTASYNC_SUCCESS
订阅函数:rc = MQTTAsync_subscribe(client, szSubTopicBuffer, QOS, &opts)) != MQTTASYNC_SUCCESS
二:给Cursor提业务需求
首先整理整个需求,分为:注册,总召唤,分召唤,主动上送,遥控预置,遥控执行,心跳,历史召唤。首先是注册信息,将上面的Client_ID,用户名和密码,填入到相关是数据表中,等待和网关的链接。其中注册和主动上送是需要设备(网关)按照发布的方式主动上送到MQTT服务器。总召,分召,遥控预置,遥控执行,心跳,历史召唤都是由网关订阅主站主题后解析相关信息再进行数据的发布。
由于我使用Cursor前已经将前面的连接服务器的相关功能完成,现在需要让他帮我检查和完善整个代码思路是否正确
1:给Cursor提需求
问:请你帮我看看我添加的pMqtt->emCustomType == NT_CUSTOM客户的MQTT功能是否正确,还有那些地方需要修改完善。
答:我先聚焦你这次改动点:全局检索 `pMqtt->emCustomType == NT_CUSTOM` 的分支落点,然后对照 MQTT 主流程(连接、订阅、发布、回调、重连)逐段检查是否有逻辑遗漏或潜在风险。
[13 tools called]
## 结论(先说结论)
你这版 `pMqtt->emCustomType == NT_CUSTOM` 还**不正确**,有几处会导致**功能不完整**甚至**运行时崩溃/未定义行为**。下面按严重级别给你列问题和建议。
---
## 关键问题(按严重程度)
### 1) **高危:NT 下行回调函数签名不匹配,存在未定义行为**
`NT_SETCMD_INFO.pfnMsgHandler` 定义为 `int (*)(void*, cJSON*)`,但初始化时传入了 `Prepare_C100_BootNotification(void*)` 这类单参数函数。后续实际调用时传了两个参数,属于 UB(轻则异常,重则崩溃)。
```49:87:/home/esp_builder/esp/NT_DigitalEnergy.h
typedef int (*MSG_NTSETCMD_HANDLER)(void* pArg, cJSON *json);
typedef struct tag_NT_SetCmd_Type
{
NT_SETCMD_TYPE emSetCmdType;
char szSubTopic[64];
MSG_NTSETCMD_HANDLER pfnMsgHandler;
}NT_SETCMD_INFO;
```
```321:326:/home/esp_builder/esp/NT_DigitalEnergy_Pub.c
INIT_NT_SET(pd, NT_SetCmdType_AllCall, "allcall_report", Prepare_C100_BootNotification);
INIT_NT_SET(pd, NT_SetCmdType_MetesCall, "metescall_report", Prepare_C100_BootNotification);
...
```
```1074:1078:/home/esp_builder/esp/es_mqtt_main_old4async.c
if(strstr(topicName, szSubTopicBuffer) != NULL)
{
if(pMqtt->stNTSetCmdIndoList[n].pfnMsgHandler((void*)pMqtt, json) == -1)
```
**建议**:给 NT 下行单独实现 `int Handler_xxx(void*, cJSON*)` 适配函数;不要把旧的 `Prepare_*` 直接塞到 `NT_SETCMD_INFO`。
---
### 2) **高危:NT 发布表只初始化了 2 项,但主循环会调用 20+ 项**
`Init_NT_MqttMsgInfo()` 只 `INIT_NT_MQTT` 了 `ARR` 和 `PCS` 两项;`Pub_NT_MsgToServer()` 却会访问大量索引(CLU/EMU/FIRE/.../CMD),未初始化函数指针会被调用,极易崩溃。
```314:318:/home/esp_builder/esp/NT_DigitalEnergy_Pub.c
INIT_NT_MQTT(p, NT_MQTT_TYPE_ARR, "register", NT_MQTT_MSG_C2S, Prepare_C100_Resigterinfo);
INIT_NT_MQTT(p, NT_MQTT_TYPE_PCS, "realtime_report",NT_MQTT_MSG_C2S, Prepare_C200_RealtimeReport);
```
```428:438:/home/esp_builder/esp/NT_DigitalEnergy_Pub.c
if((UINT)(tmNow - pMqtt->stNTmqttInfoList[NT_MQTT_TYPE_CLU].tm_LastSend) >= pMqtt->nSendTimeInterval)
{
pMqtt->stNTmqttInfoList[NT_MQTT_TYPE_CLU].pfnMsNTandler((void*)pMqtt, 0);
Publish_NT_MqttMessage(...);
}
```
**建议**:
- 要么把所有 `NT_MQTT_TYPE_* / NT_STATUS_* / NT_CMD_*` 全部初始化;
- 要么在发布前先判空 `if (pfnMsNTandler == NULL) continue;`,避免崩溃。
---
### 3) **高危:订阅主题数量定义与初始化不一致,3 个以外的命令永远收不到**
`NT_SUBTOPIC_NUM` 定义为 3,但你初始化了 6 个 NT 下行命令。订阅和匹配循环都只跑 3 次,后 3 个主题永远不订阅/不匹配。
```7:7:/home/esp_builder/esp/NT_DigitalEnergy.h
#define NT_SUBTOPIC_NUM 3
```
```321:326:/home/esp_builder/esp/NT_DigitalEnergy_Pub.c
INIT_NT_SET(...); // 共 6 条
```
```1448:1452:/home/esp_builder/esp/es_mqtt_main_old4async.c
for(n = 0; n < NT_SUBTOPIC_NUM; n++)
{
snprintf(szSubTopicBuffer, ..., "%s/%s", pMqtt->szSelfTopic, pMqtt->stNTSetCmdIndoList[n].szSubTopic);
MQTTAsync_subscribe(...);
}
```
**建议**:`NT_SUBTOPIC_NUM` 改成 `MAX_NT_SETCMD`,或者循环按 `MAX_NT_SETCMD`。
---
### 4) **中高风险:`snprintf` 把 payload 当 format 使用,存在格式串风险**
```173:173:/home/esp_builder/esp/NT_DigitalEnergy_Pub.c
snprintf(pMqtt->szSendBuffer, MAX_MQTT_BUFFER_LEN, pMsg->szJsonData);
```
如果内容里包含 `%`,会被当格式解析,存在风险/乱码。
**建议**:改为
`snprintf(pMqtt->szSendBuffer, MAX_MQTT_BUFFER_LEN, "%s", pMsg->szJsonData);`
---
### 5) **中风险:`Prepare_C200_RealtimeReport` 没有 return,函数签名是 int**
```290:293:/home/esp_builder/esp/NT_DigitalEnergy_Pub.c
int Prepare_C200_RealtimeReport(void* pArg)
{
}
```
这会产生未定义返回值;调用方如果依赖返回码会有问题。
**建议**:至少返回 `0/-1`,并补齐 JSON 封装逻辑。
---
### 6) **中风险:注册报文 `ts` 字段写法不正确(二进制时间当字符串)**
```280:283:/home/esp_builder/esp/NT_DigitalEnergy_Pub.c
get_current_bcd_time_fixed(bootInfo.system_time);
cJSON_AddStringToObject(pRoot, "ts", bootInfo.system_time);
```
`system_time` 是 `BYTE[8]`,不是 C 字符串(无 `\0` 保证),会导致脏数据或越界读取。
**建议**:
- 若协议要 BCD 字节:改成数组字段(`cJSON_AddItemToObject` + array);
- 若要字符串:先转十六进制文本或 `YYYY-MM-DD HH:MM:SS`。
---
## 你这次 NT_CUSTOM 分支里“做对了”的点
- 已在主循环里把 NT 发布入口接进来了:`Pub_NT_MsgToServer(pMqtt)`。
- 已在连接后订阅流程里加了 NT 订阅分支。
- 已在消息回调里加了 NT topic 路由分支。
这些方向是对的,但当前实现仍缺“完整初始化 + 函数契约一致性”。
---
## 建议你下一步最小修复顺序(工程化)
1. **先修函数签名**(最优先,防崩溃):NT 下行回调统一改成 `int xxx(void*, cJSON*)`。
2. **修订阅数量**:`NT_SUBTOPIC_NUM -> MAX_NT_SETCMD`。
3. **补齐 NT 发布表初始化** 或在发布前加空指针保护。
4. **修 `snprintf` 格式串** 和 `Prepare_C200_RealtimeReport` 返回值。
5. **修 `ts` 字段编码**,避免协议/内存问题。
如果你愿意,我可以直接按这 5 步给你出一版可编译的补丁(先做“最小安全修复版”,再做“协议完善版”)。
总结:Curor直接将整个MQTT连接思路总结了一下,然后把我代码里面有一些错误指了出来,由于业务相关的代码我还没有加进去,这里面有一些错误也帮我指了出来。
问:请你帮我修改。
答:我来直接帮你改成“先可稳定运行”的版本:优先修崩溃风险(回调签名、数组越界/未初始化调用、topic循环数量),再修明显协议/字符串问题(`snprintf`、`ts` 字段、空返回)。改完我会再快速自检一遍关键分支。
[6 tools called]
已按你这版代码直接做了“先稳定运行”的修改,重点修了会崩溃/错行为的问题。
### 我帮你改了什么
- 修正 NT 订阅数量定义
- `NT_SUBTOPIC_NUM` 从 `3` 改为 `6`(对应你实际初始化的 6 个订阅命令)。
- 文件:`moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy.h`
- 修正 NT 下行回调签名不匹配(高危)
- 增加了 `NT_HandleAllcall/Metescall/...` 这类适配函数,签名统一为 `int(void*, cJSON*)`。
- `Init_NT_MqttMsgInfo()` 里 `INIT_NT_SET` 改为绑定这些新回调,不再直接绑 `Prepare_C100_BootNotification(void*)`。
- 文件:`moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy_Pub.c`
- 防止 NT 发布表未初始化索引被调用导致崩溃
- 增加 `NT_NoOpPublish`,把 `stNTmqttInfoList` 未显式配置的项补成 no-op。
- 在 `Publish_NT_MqttMessage()` 中增加空 topic 保护,空 topic 直接返回 `-1`,不发送。
- 文件:`moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy_Pub.c`
- 修复格式串风险
- `snprintf(..., pMsg->szJsonData)` 改为 `snprintf(..., "%s", pMsg->szJsonData)`。
- 文件:`moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy_Pub.c`
- 修复 `Prepare_C200_RealtimeReport()` 无返回值
- 现在返回 `0`(占位实现,避免 UB)。
- 文件:`moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy_Pub.c`
- 修复 `ts` 字段写入错误
- 原来把 `BYTE[8]` 直接当字符串塞到 JSON。
- 现在新增 `BcdTimeToHexString()`,先转为 hex 文本再 `cJSON_AddStringToObject`。
- 文件:`moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy_Pub.c`
---
### 当前状态
- 代码级检查:已通过(本地 lints 无报错)。
- 模块编译验证:在你当前环境下 `make` 无法直接跑(缺少 `include.mk` 的上层构建环境变量),不是本次改动语法错误导致。
---
### 还建议你下一步补的点(功能完善)
1. `Prepare_C200_RealtimeReport()` 现在是占位返回,建议尽快补齐真实报文。
2. 目前 NT 下行 6 个命令都复用“注册上报”适配函数,仅用于“先跑通不崩”;建议按协议分别实现。
3. `Init_NT_MqttMsgInfo()` 只显式配置了 2 个上行主题,后续可按协议把其他 `NT_MQTT_TYPE_* / NT_STATUS_* / NT_CMD_*` 全部补齐,减少 no-op。
如果你要,我可以继续帮你把 **6 个 NT 下行命令处理函数**按你协议字段(总召/分召/遥控预置/执行/心跳/历史召)拆开并填成可用版本。
总结:通过前面的分析和错误总结,Cursor执行了修改,把我空留的代码功能添加了上去,把优先修崩溃风险(回调签名、数组越界/未初始化调用、topic循环数量),再修明显协议/字符串问题(`snprintf`、`ts` 字段、空返回)修改了,但是缺少了编译环境,这里的make没有通过,不过基本上解决了一些错误和问题。
问:我想成功的连接NT_CUSTOM,连接填入的相关信息如下:1. 地址 IP:储能云端URL:10.10.0.109,普通物联卡和省综 APN 卡地址不同。
2. 端口 Port:储能云端URL:18603
请联系平台人员获取
3. 用户名密码:MQTT 用户名:yfyjs,MQTT 密码:Fs1w3#f%sp8M
业务人员分配(线下)
4. Client_ID:
填写业务人员分配的网关关联编码 dcode(对应储能:设备编号ESS Device ID)
5. 加密证书:
SSL 加密(双向认证) , 证书线下获取。(数据信息:升级mTLS双向认证文件)
6. 发布和订阅主题
MQTT主题类型+主题后缀名:
发布:jssz/puc/{tag}/{dcode}/ register
订阅:jssz/puc/{tag}/{dcode}/register/ack
tag:为版本号,目前为 v2.0。dcode:物联平台分配的网关关联编码
请问按照目前的代码,我相连接对方平台的MQTT服务器,我的代码是否能成功连接,并且发送注册Prepare_C100_Resigterinfo数据,参数应该怎么配置,那些信息填入那些位置。
答:我先基于当前代码把“能否连上 NT 平台”给你做一次配置映射和可行性结论,重点核对:URL/端口、用户名密码、ClientID、主题、mTLS 证书这几项在代码里分别落到哪些参数位。
[10 tools called]
可以直接给你结论:**按当前代码,有机会连上 NT_CUSTOM 并发布 `register`,但不保证完整对接成功**。
原因是“连接层”基本具备,但“订阅 `register/ack` 和 ACK处理”目前与您给的平台主题规范不一致。
---
## 1) 你这套参数在当前代码里的映射(最重要)
| 平台参数 | 代码配置位置 | 需要填什么 |
|---|---|---|
| URL + 端口 | 参数 `id=1, subId=25` -> `pMqtt->szServerUrl` | 建议填:`ssl://10.10.0.109:18603` |
| Client_ID (dcode) | 参数 `id=1, subId=2` -> `pMqtt->szClientID` | 填你分配的 dcode(ESS Device ID) |
| 用户名 | 参数 `id=1, subId=32` -> `pMqtt->szUserName` | `yfyjs` |
| 密码 | 参数 `id=1, subId=33` -> `pMqtt->szPassWord` | `Fs1w3#f%sp8M` |
| 客户化类型 | 参数 `id=1, subId=87` -> `pMqtt->emCustomType` | 设为 `NT_CUSTOM`(枚举值 2) |
| TLS认证级别 | 参数 `id=1, subId=30` -> `pMqtt->emAuthLevel` | 设为 `TLS_AUTH_Mutual`(双向认证) |
| MQTT实例类型 | 参数 `id=1, subId=10` -> `pMqtt->emRepInstType` | 设为 `REP_TYPE_MQTT_SELFTOPIC` |
| selfTopic前缀 | 参数 `id=1, subId=35` -> `pMqtt->szSelfTopic` | 填:`jssz/puc/v2.0/{dcode}` |
| 发送周期 | 参数 `id=1, subId=90` -> `pMqtt->nSendTimeInterval` | 建议先 30~60 秒 |
---
## 2) 证书文件在代码中的固定路径(必须满足)
当前代码固定读取:
- CA:`/app/config/cacert.pem`
- 客户端证书:`/app/config/client.pem`
- 客户端私钥:`/app/config/client.key`
也就是你拿到的 mTLS 文件要按这三个文件名放到该目录,否则 TLS 握手会失败。
---
## 3) 按你平台规范,实际主题会变成什么
你要求:
- 发布:`jssz/puc/{tag}/{dcode}/register`
- 订阅:`jssz/puc/{tag}/{dcode}/register/ack`
当前 NT 发布逻辑是:`{selfTopic}/{NT子主题}`,其中注册子主题是 `register`。
所以只要 `selfTopic = jssz/puc/v2.0/{dcode}`,发布会是:
- **发布实际 = `jssz/puc/v2.0/{dcode}/register`**(匹配你要求)
---
## 4) 当前代码的关键限制(会影响“完整成功”)
### A. `register/ack` 订阅不匹配
NT 订阅现在不是 `register/ack`,而是这 6 个:
- `allcall_report`
- `metescall_report`
- `control_check`
- `control`
- `hearbeat`
- `metescall_report_his`
也就是会订阅:`{selfTopic}/{上面之一}`,**不会订阅 `{selfTopic}/register/ack`**。
### B. ACK消息处理逻辑也不是按 `register/ack` 做的
即使你手工让它订阅 `register/ack`,目前 NT 回调分支也按上述 6 类命令路由,不会专门处理注册 ACK 语义。
### C. `Prepare_C100_Resigterinfo` 报文内容较简
当前注册上报只发了类似 `ip`、`ts`,并非完整设备注册字段(如果平台要求更全字段,可能返回失败)。
---
## 5) 回答你的核心问题
### Q1:现在代码能不能连上 MQTT 服务器?
**在参数配置正确 + 证书路径正确 + 服务端接受当前 TLS/ALPN 的前提下,可以连上。**
### Q2:能不能发出 `Prepare_C100_Resigterinfo` 注册数据?
**可以发出。**
NT 主循环会调用 `Pub_NT_MsgToServer()`,其中 `NT_MQTT_TYPE_ARR` 对应 `register`。
### Q3:按你给的平台规范,是否“完整对接成功”?
**大概率不完整**,主要卡在:
- 未订阅 `register/ack`
- 未处理 `register/ack`
- 注册 payload 字段可能不全
---
## 6) 你现在可以先这样配(最小可运行)
1. `1/87 = NT_CUSTOM`
2. `1/10 = REP_TYPE_MQTT_SELFTOPIC`
3. `1/25 = ssl://10.10.0.109:18603`
4. `1/2 = {dcode}`
5. `1/32 = yfyjs`
6. `1/33 = Fs1w3#f%sp8M`
7. `1/30 = TLS_AUTH_Mutual`
8. `1/35 = jssz/puc/v2.0/{dcode}`
9. 部署证书到 `/app/config/cacert.pem /app/config/client.pem /app/config/client.key`
---
如果你愿意,我下一步可以直接给你改两处,做到与你平台协议完全贴合:
1) 把 NT 订阅改为 `register/ack`
2) 增加 `register/ack` 的解析处理和注册结果状态流转。
总结:我又将整个连接思路复述了一遍,寻求Cursor是否能够正常了连接上MQTT服务器(未测试),目的是为了问他我的整个开发思路是否正确,检查MQTT整体的开发思路。
问:1. 测点信息,最后 4 位,对应主站测点库的测点标识,例如测点标识“470001” , 后面 0001 代表通讯状态; “470002” ,后面 0002 代表 a 相电压。
2. 设备信息
除去后 4 位,前面为设备唯一标识,例如 470001,前面 47 代表设 备唯一标识; 1470002,前面 147 代表设备唯一标识。
3. 设备类型
设备类型代表设备在主站测点库的类型,参照 CSV 文件如实上送 即可。
4. 测点类型
测点类型为枚举型,详细信息如下:
0 :遥信
1 :遥测
2 :遥控
3 :遥调
4 :告警
5 :遥脉
9 :其他
5. CSV 文件示例:
"测点标识",设备类型,设备名称,测点名称,测点类型 "180100002 ",0101,变压器 10KV1,a 相电压,"1 " "180100003 ",0101,变压器 10KV1,b 相电压,"1 " "180100004 ",0101,变压器 10KV1,c 相电压,"1 " "180110002 ",0101,变压器 10KV2,a 相电压,"1 " "180110217 ",0101,变压器 10KV2,反向冻结电量 15min,"1 " "12070051",0105,逆变器 3NB01,有功功率,"1 " "12070061",0105,逆变器 3NB01,当日发电量,"5 " "12080051",0105,逆变器 3NB02,有功功率,"1 " "12080061",0105,逆变器 3NB02,当日发电量,"5 "
总召下发
主题:jssz/puc/{tag}/{dcode}/allcall_report 发布方:主站
订阅方:网关 内容:
{
"callname":"baba156e121e48e29ffebce10c3a7290",
"ts":"2021-10-22 9:51:00"
}
总召数据上报应答
主题:jssz/puc/{tag}/{dcode}/allcall_report/ack 发布方:网关
订阅方:主站 内容:
{
"callname":"baba156e121e48e29ffebce10c3a7290",
"psn":1,
"dtype":"0102",
"data":
{"470003":1,"1470003":1,"470004":1,"2470012":1,"1470023":1},
"ts":"2021-10-22 9:51:00"
}
说明:应答报文,每包有且仅有一个 dytpe 值;不同 dtype 的测 点需要分包上送。
主动上送
变化实时数据主动上送
设备侧变化数据上送,重要数据,量比较小,单次报文不 超过100个点的数据。
主题:jssz/puc/{tag}/{dcode}/realtime_report 发布方:网关
订阅方:主站 内容:
{
"psn":1,
"dtype":"0102",
"data":
{"470003":1,"1470003":1,"470004":1,"2470012":1,"1470023":1},
"ts":"2021-10-22 9:51:00"
}
说明:应答报文,每包有且仅有一个 dytpe 值;不同 dtype 的测 点需要分包上送。
psn:包序号,每次从 1 开始 累加,到 99999 时复位 到 1,用于区分一次上送的不同的包
dtype:设备类型 cvs 文件中导出的字段值,同 一包中,只包涵一种设备类型, 如果存在多种设备类型,进行 多个报文包传输。
data:包含实际测点数据,该 value 是一个集合,单个测点格式:测点表示: 值例如: "470003":1
ts:该条报文产生时间 上报、下发时间 yyyy-MM-dd HH:mm:ss
附件二:CSV文件示例
"测点标识",设备类型,设备名称,测点名称,测点类型 "180100002 ",0101,变压器 10KV1,a 相电压,"1 " "180100003 ",0101,变压器 10KV1,b 相电压,"1 " "180100004 ",0101,变压器 10KV1,c 相电压,"1 " "180100010 ",0101,变压器 10KV1,a 相电流,"1 " "180100011 ",0101,变压器 10KV1,b 相电流,"1 " "180100012 ",0101,变压器 10KV1,c 相电流,"1 " "180100021 ",0101,变压器 10KV1,总有功功率,"1 "
"180100034 ",0101,变压器 10KV1,总功率因数,"1 "
"180100036 ",0101,变压器 10KV1,正向有功电能,"5 "
"180100037 ",0101,变压器 10KV1,反向有功电能,"5 "
"180100096 ",0101,变压器 10KV1,累计电量,"1 "
"180100213 ",0101,变压器 10KV1,日用电量,"1 "
"180100214 ",0101,变压器 10KV1,月用电量,"1 "
"180100215 ",0101,变压器 10KV1,年用电量,"1 "
"180100216 ",0101,变压器 10KV1,正向冻结电量 15min,"1 "
"180100217 ",0101,变压器 10KV1,反向冻结电量 15min,"1 "
"180100220 ",0101,变压器 10KV1,年累计反向电量,"1 "
"180110002 ",0101,变压器 10KV2,a 相电压,"1 "
请你根据上面的总召allcall_report和主动上送realtime_report帮我完成代码功能
答;我会先把 `NT_DigitalEnergy_Pub.c` 里与 `allcall_report`、`realtime_report` 相关的现状读全,确认可复用的数据来源(如 `pMqtt->clientInfoSum`、现有上报函数),然后直接补上:总召入站处理 + 总召应答上送 + 主动上送报文构造(含 `psn/dtype/data/ts`)。
[1 tool called]
我会按你给的协议先做“可跑通的一版实现”:
1) 实现 `allcall_report` 下发解析并回 `allcall_report/ack`;
2) 实现 `realtime_report` 主动上送报文(`psn/dtype/data/ts`);
3) 先用工程里现成运行量映射一组测点,后续你拿到 CSV 全量映射再扩展。现在先把主流程闭环打通。
[3 tools called]
核心代码已经补完并通过静态检查;我再快速核对一下回调链路里 `allcall_report` 的处理是否会触发到这个新 `NT_HandleAllcall`,以及 topic 拼接是否和 `jssz/puc/{tag}/{dcode}` 规则一致。
[5 tools called]
已按你给的协议把 `allcall_report` 和 `realtime_report` 主链路在代码里补齐了,落在 `NT_DigitalEnergy_Pub.c`。
关键实现如下:
- **总召下发处理**:收到 `allcall_report` 后,解析 `callname`,构造应答并发布到 `allcall_report/ack`
- **主动上送**:实现 `Prepare_C200_RealtimeReport()`,生成 `psn/dtype/data/ts` 的实时上送 JSON
- **协议字段规则**:
- `psn`:1~99999 循环
- `dtype`:当前先固定 `"0102"`(单包单 dtype)
- `ts`:`yyyy-MM-dd HH:mm:ss`
- `data`:`"测点标识":"值"` 形式
- **测点映射**:先用工程现有实时汇总量(`clientInfoSum`)做了一组可联调映射,保证先跑通
```177:224:code/src/moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy_Pub.c
static void GetCurrentTimeString(char *out, size_t out_len) { ... }
static UINT NextNtPsn(void) { ... }
static void BuildNtDataPack(MQTT_DATA_ROUGH *pMqtt, cJSON *pData)
{
A_BLOB_SEMS_CLIENTINFO_SUM *sum = &pMqtt->clientInfoSum;
cJSON_AddNumberToObject(pData, "470001", sum->emCCUStateSum);
cJSON_AddNumberToObject(pData, "470002", sum->fACDC_RealTime_VoltSum);
cJSON_AddNumberToObject(pData, "470003", sum->fActvPwr_PCSGrpSum);
cJSON_AddNumberToObject(pData, "470004", sum->f_PcabMeterSum);
cJSON_AddNumberToObject(pData, "470005", sum->fSOCSum);
}
```
```350:423:code/src/moduals/reporters/es_mqtt_reporter/NT_DigitalEnergy_Pub.c
int Prepare_C200_RealtimeReport(void* pArg)
{
...
cJSON_AddNumberToObject(pRoot, "psn", (int)NextNtPsn());
cJSON_AddStringToObject(pRoot, "dtype", "0102");
BuildNtDataPack(pMqtt, pData);
cJSON_AddItemToObject(pRoot, "data", pData);
cJSON_AddStringToObject(pRoot, "ts", szTs);
Send_NT_Call(pMqtt, pRoot, CALL_SRC_Normal, 0, TRUE);
return 0;
}
static int NT_HandleAllcall(void* pArg, cJSON *json)
{
...
cJSON_AddStringToObject(pRoot, "callname", pCallName->valuestring);
cJSON_AddNumberToObject(pRoot, "psn", (int)NextNtPsn());
cJSON_AddStringToObject(pRoot, "dtype", "0102");
BuildNtDataPack(pMqtt, pData);
cJSON_AddItemToObject(pRoot, "data", pData);
cJSON_AddStringToObject(pRoot, "ts", szTs);
Send_NT_Call(pMqtt, pRoot, CALL_SRC_Normal, 0, TRUE);
Publish_NT_MqttMessage(pMqtt, NT_MQTT_TYPE_ARR, "allcall_report/ack");
return 0;
}
```
你接下来只要做这一步,就能和你给的 CSV 规范完全对齐:
- 把 `BuildNtDataPack()` 里的点号与取值逻辑,替换成你们主站 CSV 的**全量映射**(按 `dtype` 分包)
- 如果一个周期内有多个 `dtype`,在 `Prepare_C200_RealtimeReport()` 里按 `dtype` 循环分多包上送(每包一个 `dtype`)
如果你要,我下一步可以直接继续帮你把“CSV 驱动映射 + 多 dtype 自动分包 + 每包最多 100 点”的完整版本也一次性补上。
总结:这里我直接将总召和主动上送的业务要求发给了它,Cursor直接帮我整理出来了两个数据上报的JSON格式和点位帮我梳理了出来,虽然内容还不是很完善,但是基本上的功能已经具备了,相关的业务无非就是将对于的点位数据和客户的测点标识等一一对应,这种属于重复性的繁琐的工作量,必然是交给AI最好,将整个文本文档喂给Cursor,可以将数据信息一一对接。
三:Cursor编程总结
这次只是比较简单的业务开发,Cursor对于这里开发完成的还是比较容易,使用的token也不多,不过整体来看,他能帮我完成相当一部分重复性的工作,对于重复量大,技术含量不高的内容,AI能够帮助完成相当多的工作量,同时也能检查逻辑错误,语法错误,代码功能漏洞等,在逻辑上也能给出解决方案,后续的一些编译和测试的任务还需要我自己来。总的来说Cursor比较强大,下次有逻辑性强的工作内容我将使用他来辅助,进行检查和为我提供开发思路。
除了Cursor还有Claude code也是很强大的编码工具,下次我使用Claude code来完成业务需求。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)