issue-18 优化代码(只保证编译通过没检查)
This commit is contained in:
@@ -29,23 +29,27 @@ const (
|
||||
|
||||
// ChirpStackListener 是一个监听器, 用于监听ChirpStack反馈的设备上行事件
|
||||
type ChirpStackListener struct {
|
||||
logger *logs.Logger
|
||||
sensorDataRepo repository.SensorDataRepository
|
||||
deviceRepo repository.DeviceRepository
|
||||
deviceCommandLogRepo repository.DeviceCommandLogRepository
|
||||
logger *logs.Logger
|
||||
sensorDataRepo repository.SensorDataRepository
|
||||
deviceRepo repository.DeviceRepository
|
||||
deviceCommandLogRepo repository.DeviceCommandLogRepository
|
||||
pendingCollectionRepo repository.PendingCollectionRepository // 新增
|
||||
}
|
||||
|
||||
// NewChirpStackListener 创建一个新的 ChirpStackListener 实例
|
||||
func NewChirpStackListener(
|
||||
logger *logs.Logger,
|
||||
sensorDataRepo repository.SensorDataRepository,
|
||||
deviceRepo repository.DeviceRepository,
|
||||
deviceCommandLogRepo repository.DeviceCommandLogRepository,
|
||||
) *ChirpStackListener {
|
||||
pendingCollectionRepo repository.PendingCollectionRepository, // 新增
|
||||
) ListenHandler { // 返回接口类型
|
||||
return &ChirpStackListener{
|
||||
logger: logger,
|
||||
sensorDataRepo: sensorDataRepo,
|
||||
deviceRepo: deviceRepo,
|
||||
deviceCommandLogRepo: deviceCommandLogRepo,
|
||||
logger: logger,
|
||||
sensorDataRepo: sensorDataRepo,
|
||||
deviceRepo: deviceRepo,
|
||||
deviceCommandLogRepo: deviceCommandLogRepo,
|
||||
pendingCollectionRepo: pendingCollectionRepo, // 新增
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,54 +197,92 @@ func (c *ChirpStackListener) handleUpEvent(event *UpEvent) {
|
||||
return
|
||||
}
|
||||
|
||||
// 3.2 Protobuf 反序列化
|
||||
var payload proto.UplinkPayload
|
||||
if err := gproto.Unmarshal(decodedData, &payload); err != nil {
|
||||
c.logger.Errorf("Protobuf 反序列化 'up' 事件的解码后 Data 失败: %v, Decoded Data: %x", err, decodedData)
|
||||
// 3.2 解析外层 "信封"
|
||||
var instruction proto.Instruction
|
||||
if err := gproto.Unmarshal(decodedData, &instruction); err != nil {
|
||||
c.logger.Errorf("解析上行 Instruction Protobuf 失败: %v, Decoded Data: %x", err, decodedData)
|
||||
return
|
||||
}
|
||||
c.logger.Infof("成功解析 Protobuf 数据, 包含 %d 条读数", len(payload.Readings))
|
||||
|
||||
// 3.3 遍历处理每一条读数
|
||||
for _, reading := range payload.Readings {
|
||||
// 3.3.1 根据物理地址查找对应的传感器设备
|
||||
sensorDevice, err := c.deviceRepo.FindByParentAndPhysicalAddress(regionalController.ID, reading.BusNumber, reading.BusAddress)
|
||||
// 3.3 检查是否是采集响应
|
||||
if instruction.Method != proto.MethodType_COLLECT {
|
||||
c.logger.Infof("收到一个非采集响应的上行指令 (Method: %s),无需处理。", instruction.Method.String())
|
||||
return
|
||||
}
|
||||
|
||||
// 2.4 解包内层 CollectResult
|
||||
var collectResp proto.CollectResult
|
||||
if err := instruction.Data.UnmarshalTo(&collectResp); err != nil {
|
||||
c.logger.Errorf("解包数据信息失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
correlationID := collectResp.CorrelationId
|
||||
c.logger.Infof("成功解析采集响应 (CorrelationID: %s),包含 %d 个值。", correlationID, len(collectResp.Values))
|
||||
|
||||
// 3. 根据 CorrelationID 查找待处理请求
|
||||
pendingReq, err := c.pendingCollectionRepo.FindByCorrelationID(correlationID)
|
||||
if err != nil {
|
||||
c.logger.Errorf("处理采集响应失败:无法找到待处理请求 (CorrelationID: %s): %v", correlationID, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查状态,防止重复处理
|
||||
if pendingReq.Status != models.PendingStatusPending && pendingReq.Status != models.PendingStatusTimedOut {
|
||||
c.logger.Warnf("收到一个已处理过的采集响应 (CorrelationID: %s, Status: %s),将忽略。", correlationID, pendingReq.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// 4. 匹配数据并存入数据库
|
||||
deviceIDs := pendingReq.CommandMetadata
|
||||
values := collectResp.Values
|
||||
if len(deviceIDs) != len(values) {
|
||||
c.logger.Errorf("数据不匹配:下行指令要求采集 %d 个设备,但上行响应包含 %d 个值 (CorrelationID: %s)", len(deviceIDs), len(values), correlationID)
|
||||
// TODO 数量不匹配是否全改成失败
|
||||
// 即使数量不匹配,也更新状态为完成,以防止请求永远 pending
|
||||
err = c.pendingCollectionRepo.UpdateStatusToFulfilled(correlationID, event.Time)
|
||||
if err != nil {
|
||||
c.logger.Errorf("查找传感器设备失败: %v", err)
|
||||
continue // 继续处理下一条读数
|
||||
c.logger.Errorf("处理采集响应失败:无法更新待处理请求 (CorrelationID: %s) 的状态为完成: %v", correlationID, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ✨ 核心修正: 直接从 models 包的公开 map 中查找转换关系 ✨
|
||||
sensorDataType, ok := models.DeviceSubTypeToSensorDataTypeMap[sensorDevice.SubType]
|
||||
if !ok {
|
||||
// 如果一个设备子类型不在 map 中, 说明它不是一个需要记录数据的传感器, 这属于正常情况, 无需记录日志.
|
||||
for i, deviceID := range deviceIDs {
|
||||
value := values[i]
|
||||
dev, err := c.deviceRepo.FindByID(deviceID)
|
||||
if err != nil {
|
||||
c.logger.Errorf("处理采集数据失败:无法找到设备 (ID: %d): %v", deviceID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
sensorDataType, ok := models.DeviceSubTypeToSensorDataTypeMap[dev.SubType]
|
||||
if !ok {
|
||||
c.logger.Warnf("设备 %d 的子类型 '%s' 没有对应的传感器数据类型,跳过记录。", dev.ID, dev.SubType)
|
||||
continue
|
||||
}
|
||||
|
||||
// 3.3.2 根据转换后的 sensorDataType 构建具体的数据结构
|
||||
var sensorData interface{}
|
||||
switch sensorDataType {
|
||||
case models.SensorDataTypeTemperature:
|
||||
sensorData = models.TemperatureData{
|
||||
TemperatureCelsius: float64(reading.Value),
|
||||
}
|
||||
sensorData = models.TemperatureData{TemperatureCelsius: float64(value)}
|
||||
case models.SensorDataTypeHumidity:
|
||||
sensorData = models.HumidityData{
|
||||
HumidityPercent: float64(reading.Value),
|
||||
}
|
||||
sensorData = models.HumidityData{HumidityPercent: float64(value)}
|
||||
case models.SensorDataTypeWeight:
|
||||
sensorData = models.WeightData{
|
||||
WeightKilograms: float64(reading.Value),
|
||||
}
|
||||
sensorData = models.WeightData{WeightKilograms: float64(value)}
|
||||
default:
|
||||
// 这个 case 理论上不会被触发
|
||||
c.logger.Warnf("未处理的传感器数据类型 '%s' (设备ID: %d)", sensorDataType, sensorDevice.ID)
|
||||
c.logger.Warnf("未处理的传感器数据类型 '%s' (设备ID: %d)", sensorDataType, dev.ID)
|
||||
continue
|
||||
}
|
||||
|
||||
// 3.3.3 记录传感器数据
|
||||
c.recordSensorData(regionalController.ID, sensorDevice.ID, event.Time, sensorDataType, sensorData)
|
||||
c.logger.Infof("成功记录传感器数据: 设备ID=%d, 类型=%s, 值=%.2f", sensorDevice.ID, sensorDataType, reading.Value)
|
||||
c.recordSensorData(pendingReq.DeviceID, dev.ID, event.Time, sensorDataType, sensorData)
|
||||
c.logger.Infof("成功记录传感器数据: 设备ID=%d, 类型=%s, 值=%.2f", dev.ID, sensorDataType, value)
|
||||
}
|
||||
|
||||
// 5. 更新请求状态为“已完成”
|
||||
if err := c.pendingCollectionRepo.UpdateStatusToFulfilled(correlationID, event.Time); err != nil {
|
||||
c.logger.Errorf("更新待采集请求状态为 'fulfilled' 失败 (CorrelationID: %s): %v", correlationID, err)
|
||||
} else {
|
||||
c.logger.Infof("成功完成并关闭采集请求 (CorrelationID: %s)", correlationID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user