记录任务下发历史和接收是否成功

This commit is contained in:
2025-09-25 00:17:01 +08:00
parent 6b931648dc
commit e2e21601f4
7 changed files with 161 additions and 29 deletions

View File

@@ -4,6 +4,8 @@ import (
"time"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/transport/lora/chirp_stack_proto/client/device_service"
"github.com/go-openapi/runtime"
httptransport "github.com/go-openapi/runtime/client"
@@ -33,11 +35,19 @@ type ChirpStackTransport struct {
authInfo runtime.ClientAuthInfoWriter
config ChirpStackConfig
deviceCommandLogRepo repository.DeviceCommandLogRepository
deviceRepo repository.DeviceRepository
logger *logs.Logger
}
// NewChirpStackTransport 创建一个新的通信实例,用于与 ChirpStack 通信。
func NewChirpStackTransport(config ChirpStackConfig, logger *logs.Logger) *ChirpStackTransport {
func NewChirpStackTransport(
config ChirpStackConfig,
logger *logs.Logger,
deviceCommandLogRepo repository.DeviceCommandLogRepository,
deviceRepo repository.DeviceRepository,
) *ChirpStackTransport {
// 使用配置中的服务器地址创建一个 HTTP transport。
// 它会使用生成的客户端中定义的默认 base path 和 schemes。
transport := httptransport.New(config.ServerAddress, client.DefaultBasePath, client.DefaultSchemes)
@@ -49,10 +59,12 @@ func NewChirpStackTransport(config ChirpStackConfig, logger *logs.Logger) *Chirp
authInfo := httptransport.APIKeyAuth("grpc-metadata-authorization", "header", config.GenerateAPIKey())
return &ChirpStackTransport{
client: apiClient,
authInfo: authInfo,
config: config,
logger: logger,
client: apiClient,
authInfo: authInfo,
config: config,
logger: logger,
deviceCommandLogRepo: deviceCommandLogRepo,
deviceRepo: deviceRepo,
}
}
@@ -80,12 +92,56 @@ func (c *ChirpStackTransport) Send(address string, payload []byte) error {
// 3. 调用生成的客户端方法来发送请求。
// c.authInfo 是您在 NewChirpStackTransport 中创建的认证信息。
_, err := c.client.DeviceService.DeviceServiceEnqueue(params, c.authInfo)
resp, err := c.client.DeviceService.DeviceServiceEnqueue(params, c.authInfo)
if err != nil {
c.logger.Errorf("设备 %s 调用ChirpStack Enqueue失败: %v", address, err)
return err
}
c.logger.Infof("设备 %s 调用ChirpStack Enqueue成功", address)
// 4. 成功发送后,尝试记录下行任务
messageID := ""
if resp != nil && resp.Payload != nil && resp.Payload.ID != "" { // 根据实际结构,使用 resp.Payload.ID
messageID = resp.Payload.ID
} else {
c.logger.Warnf("ChirpStack Enqueue 响应未包含 MessageID (ID),无法记录下行任务。设备: %s", address)
// 即使无法获取 MessageID也认为发送成功因为 ChirpStack Enqueue 成功了
return nil
}
// 调用私有方法记录下行任务
if err := c.recordDownlinkTask(address, messageID); err != nil {
// 记录失败不影响下行命令的发送成功
c.logger.Errorf("记录下行任务失败 (MessageID: %s, DevEui: %s): %v", messageID, address, err)
return nil
}
c.logger.Infof("设备 %s 调用ChirpStack Enqueue成功并创建下行任务记录 (MessageID: %s)", address, messageID)
return nil
}
// recordDownlinkTask 记录下行任务到数据库
func (c *ChirpStackTransport) recordDownlinkTask(devEui string, messageID string) error {
// 获取区域主控的内部 DeviceID
regionalController, err := c.deviceRepo.FindByDevEui(devEui)
if err != nil {
c.logger.Errorf("记录下行任务失败:无法通过 DevEui '%s' 找到区域主控设备: %v", devEui, err)
return err
}
// 创建 DeviceCommandLog
record := &models.DeviceCommandLog{
MessageID: messageID,
DeviceID: regionalController.ID,
SentAt: time.Now(),
AcknowledgedAt: nil, // 初始状态为未确认
}
if err := c.deviceCommandLogRepo.Create(record); err != nil {
c.logger.Errorf("创建下行任务记录失败 (MessageID: %s, DeviceID: %d): %v", messageID, regionalController.ID, err)
return err
}
c.logger.Infof("成功创建下行任务记录 (MessageID: %s, DeviceID: %d)", messageID, regionalController.ID)
return nil
}