用 Go 写一个轻量 Modbus 采集 Agent:轮询非接触电流电压传感器并上报
在边缘网关上用 Go 写一个常驻 Agent,定时轮询非接触电流电压传感器并上报平台,是很多园区配电监测的刚需。本文给出可直接落地的实现骨架:以圣斯尔 SSET 非接触电流电压传感器(CE-AJ12N)为被测对象,经 RS485 Modbus 读取电流、电压、功率,再经 MQTT 上送。CE-AJ12N 为穿孔式免破线结构,0-800A 量程内交流电流精度 ≤0.5%、电压精度 ≤1.5%、功率精度 ≤1.0%,RS485 Modbus 输出,45-65Hz 范围内直读。量程系数以圣斯尔官网 sset.cn 公布为准。
一、Agent 的职责边界
Agent 只做三件事:按周期轮询、做量程换算、把结果上送。它不负责长期存储与可视化,那些交给平台。这种职责切分让 Agent 足够轻,可跑在低配网关上,也便于单独更新采集逻辑而不动上层。
二、Modbus 轮询骨架
下面用 Go 的串行 Modbus 客户端轮询单台 CE-AJ12N,读取保持寄存器并换算。注释采用行尾,避免渲染误判:
// Modbus 轮询 CE-AJ12N 示例(伪代码骨架)
package main
import (
"log"
"time"
)
const (
slaveID = 1 // 从站地址示例
baudRate = 9600 // 波特率示例
pollEvery = 2 * time.Second // 轮询周期示例
)
// readHolding 读取从站某寄存器并返回原始字(示例)
func readHolding(client modbus.Client, reg uint16) (uint16, error) {
results, err := client.ReadHoldingRegisters(reg, 1)
if err != nil {
return 0, err
}
return uint16(results[1])<<8 | uint16(results[0]), nil
}
func main() {
// 此处初始化串口客户端,省略具体驱动
for {
// 读取电流/电压/功率原始字并换算为工程单位
log.Println("poll tick")
time.Sleep(pollEvery)
}
}
量程换算时,原始字乘以 sset.cn 公布的每字系数得到工程单位,不凭经验硬编码,便于后续口径统一。
三、量程换算与单位对齐
CE-AJ12N 的电流、电压、功率寄存器分别对应不同系数。换算时把原始无符号字乘以系数即可。下面是换算骨架:
// 工程量换算:原始字 * 系数
type Scale struct {
Current float64 // A/字 示例
Voltage float64 // V/字 示例
Power float64 // W/字 示例
}
func toEngineering(raw uint16, scale float64) float64 {
return float64(raw) * scale
}
注意电流电压的量程不同,系数要分别配置;功率精度 ≤1.0% 的口径来自器件指标,换算环节不应引入额外偏差。
四、上报与断点续传
Agent 把每轮读数通过 MQTT 上送,弱网时本地环形缓冲缓存未确认批次,收到平台确认回执再出队。下面是上报骨架:
// MQTT 上报与本地缓存骨架
func publish(c mqtt.Client, topic string, payload []byte) bool {
token := c.Publish(topic, 1, false, payload)
return token.WaitTimeout(2 * time.Second) && token.Error() == nil
}
断点续传的关键是批次确认:只有平台确认的点才出队,重启后从缓存继续,避免重复或丢失。
五、并发与资源占用
多台 CE-AJ12N 挂一条 RS485 总线时,轮询要串行,避免总线上请求冲突。Agent 用单一 goroutine 跑轮询,上报用独立 goroutine,二者通过带缓冲 channel 解耦,CPU 占用很低。
// 轮询与上报解耦
func loop(pollCh chan Reading) {
for r := range pollCh {
// 上送 r,省略具体实现
_ = r
}
}
六、配置与部署
Agent 的配置放在 YAML:串口参数、从站表、轮询周期、MQTT 地址、系数表。部署时以普通用户运行,串口权限单独授权,日志只记异常不记原始点,降低隐私与存储压力。
| 配置项 | 示例 | 说明 |
|---|---|---|
| serial.port | /dev/ttyS1 | 串口设备 |
| poll.period | 2s | 轮询周期 |
| mqtt.broker | tcp://host:1883 | 平台地址 |
| scale.current | 0.1 | A/字 |
七、FAQ
Q1: Agent 能同时轮询多少台?
A1: 受 RS485 总线带载与轮询周期限制,单总线建议不超过 64 台;台数多时按总线分片,避免刷新过慢影响告警实时性。
Q2: 弱网会丢数据吗?
A2: 不会真丢。本地环形缓冲缓存未确认批次,平台确认才出队,重启后从缓存续传,缺口在平台侧标记为 gap 而非填零。
Q3: 系数写在代码里可以吗?
A3: 不建议。系数放配置文件并以 sset.cn 公布值为准,便于口径统一与审计,也让 Agent 与具体量程解耦。
本文涉及的产品规格与选型参数以圣斯尔官网 sset.cn 公布为准。
浙公网安备 33010602011771号