将所有Regional更改为Area
This commit is contained in:
@@ -144,3 +144,4 @@
|
||||
12. 实现任务11应的八个web接口
|
||||
13. 实现根据区域ID或设备ID清空对应阈值告警任务
|
||||
14. 设备和区域主控删除时清除对应区域阈值告警或设备阈值告警任务
|
||||
15. 将所有Regional更改为Area
|
||||
@@ -6816,6 +6816,9 @@ const docTemplate = `{
|
||||
"dto.SensorDataDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"area_controller_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -6825,9 +6828,6 @@ const docTemplate = `{
|
||||
"device_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"regional_controller_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"sensor_type": {
|
||||
"$ref": "#/definitions/models.SensorType"
|
||||
},
|
||||
|
||||
@@ -6808,6 +6808,9 @@
|
||||
"dto.SensorDataDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"area_controller_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -6817,9 +6820,6 @@
|
||||
"device_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"regional_controller_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"sensor_type": {
|
||||
"$ref": "#/definitions/models.SensorType"
|
||||
},
|
||||
|
||||
@@ -1369,14 +1369,14 @@ definitions:
|
||||
type: object
|
||||
dto.SensorDataDTO:
|
||||
properties:
|
||||
area_controller_id:
|
||||
type: integer
|
||||
data:
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
device_id:
|
||||
type: integer
|
||||
regional_controller_id:
|
||||
type: integer
|
||||
sensor_type:
|
||||
$ref: '#/definitions/models.SensorType'
|
||||
time:
|
||||
|
||||
@@ -13,7 +13,7 @@ func NewListSensorDataResponse(data []models.SensorData, total int64, page, page
|
||||
dtos[i] = SensorDataDTO{
|
||||
Time: item.Time,
|
||||
DeviceID: item.DeviceID,
|
||||
RegionalControllerID: item.RegionalControllerID,
|
||||
AreaControllerID: item.AreaControllerID,
|
||||
SensorType: item.SensorType,
|
||||
Data: json.RawMessage(item.Data),
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ type ListSensorDataRequest struct {
|
||||
type SensorDataDTO struct {
|
||||
Time time.Time `json:"time"`
|
||||
DeviceID uint `json:"device_id"`
|
||||
RegionalControllerID uint `json:"regional_controller_id"`
|
||||
AreaControllerID uint `json:"area_controller_id"`
|
||||
SensorType models.SensorType `json:"sensor_type"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
@@ -162,17 +162,17 @@ func (c *ChirpStackListener) handleUpEvent(ctx context.Context, event *UpEvent)
|
||||
logger.Infof("开始处理 'up' 事件, DevEui: %s", event.DeviceInfo.DevEui)
|
||||
|
||||
// 1. 查找区域主控设备
|
||||
regionalController, err := c.areaControllerRepo.FindByNetworkID(reqCtx, event.DeviceInfo.DevEui)
|
||||
areaController, err := c.areaControllerRepo.FindByNetworkID(reqCtx, event.DeviceInfo.DevEui)
|
||||
if err != nil {
|
||||
logger.Errorf("处理 'up' 事件失败:无法通过 DevEui '%s' 找到区域主控设备: %v", event.DeviceInfo.DevEui, err)
|
||||
return
|
||||
}
|
||||
// 依赖 SelfCheck 确保区域主控有效
|
||||
if err := regionalController.SelfCheck(); err != nil {
|
||||
logger.Errorf("处理 'up' 事件失败:区域主控 %v(ID: %d) 未通过自检: %v", regionalController.Name, regionalController.ID, err)
|
||||
if err := areaController.SelfCheck(); err != nil {
|
||||
logger.Errorf("处理 'up' 事件失败:区域主控 %v(ID: %d) 未通过自检: %v", areaController.Name, areaController.ID, err)
|
||||
return
|
||||
}
|
||||
logger.Infof("找到区域主控: %s (ID: %d)", regionalController.Name, regionalController.ID)
|
||||
logger.Infof("找到区域主控: %s (ID: %d)", areaController.Name, areaController.ID)
|
||||
|
||||
// 2. 记录区域主控的信号强度 (如果存在)
|
||||
if len(event.RxInfo) > 0 {
|
||||
@@ -187,8 +187,8 @@ func (c *ChirpStackListener) handleUpEvent(ctx context.Context, event *UpEvent)
|
||||
}
|
||||
|
||||
// 记录信号强度
|
||||
c.recordSensorData(reqCtx, regionalController.ID, regionalController.ID, event.Time, models.SensorTypeSignalMetrics, signalMetrics)
|
||||
logger.Infof("已记录区域主控 (ID: %d) 的信号强度: RSSI=%d, SNR=%.2f", regionalController.ID, rx.Rssi, rx.Snr)
|
||||
c.recordSensorData(reqCtx, areaController.ID, areaController.ID, event.Time, models.SensorTypeSignalMetrics, signalMetrics)
|
||||
logger.Infof("已记录区域主控 (ID: %d) 的信号强度: RSSI=%d, SNR=%.2f", areaController.ID, rx.Rssi, rx.Snr)
|
||||
} else {
|
||||
logger.Warnf("处理 'up' 事件时未找到 RxInfo,无法记录信号数据。DevEui: %s", event.DeviceInfo.DevEui)
|
||||
}
|
||||
@@ -316,7 +316,7 @@ func (c *ChirpStackListener) handleUpEvent(ctx context.Context, event *UpEvent)
|
||||
}
|
||||
|
||||
// 5.5 记录传感器数据
|
||||
c.recordSensorData(reqCtx, regionalController.ID, dev.ID, event.Time, valueDescriptor.Type, dataToRecord)
|
||||
c.recordSensorData(reqCtx, areaController.ID, dev.ID, event.Time, valueDescriptor.Type, dataToRecord)
|
||||
logger.Infof("成功记录传感器数据: 设备ID=%d, 类型=%s, 原始值=%f, 解析值=%.2f", dev.ID, valueDescriptor.Type, rawSensorValue, parsedValue)
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ func (c *ChirpStackListener) handleStatusEvent(ctx context.Context, event *Statu
|
||||
logger.Infof("处接收到理 'status' 事件: %+v", event)
|
||||
|
||||
// 查找区域主控设备
|
||||
regionalController, err := c.areaControllerRepo.FindByNetworkID(reqCtx, event.DeviceInfo.DevEui)
|
||||
areaController, err := c.areaControllerRepo.FindByNetworkID(reqCtx, event.DeviceInfo.DevEui)
|
||||
if err != nil {
|
||||
logger.Errorf("处理 'status' 事件失败:无法通过 DevEui '%s' 找到区域主控设备: %v", event.DeviceInfo.DevEui, err)
|
||||
return
|
||||
@@ -344,8 +344,8 @@ func (c *ChirpStackListener) handleStatusEvent(ctx context.Context, event *Statu
|
||||
signalMetrics := models.SignalMetrics{
|
||||
MarginDb: event.Margin,
|
||||
}
|
||||
c.recordSensorData(reqCtx, regionalController.ID, regionalController.ID, event.Time, models.SensorTypeSignalMetrics, signalMetrics)
|
||||
logger.Infof("已记录区域主控 (ID: %d) 的信号状态: %+v", regionalController.ID, signalMetrics)
|
||||
c.recordSensorData(reqCtx, areaController.ID, areaController.ID, event.Time, models.SensorTypeSignalMetrics, signalMetrics)
|
||||
logger.Infof("已记录区域主控 (ID: %d) 的信号状态: %+v", areaController.ID, signalMetrics)
|
||||
|
||||
// 记录电量
|
||||
batteryLevel := models.BatteryLevel{
|
||||
@@ -353,8 +353,8 @@ func (c *ChirpStackListener) handleStatusEvent(ctx context.Context, event *Statu
|
||||
BatteryLevelUnavailable: event.BatteryLevelUnavailable,
|
||||
ExternalPower: event.ExternalPower,
|
||||
}
|
||||
c.recordSensorData(reqCtx, regionalController.ID, regionalController.ID, event.Time, models.SensorTypeBatteryLevel, batteryLevel)
|
||||
logger.Infof("已记录区域主控 (ID: %d) 的电池状态: %+v", regionalController.ID, batteryLevel)
|
||||
c.recordSensorData(reqCtx, areaController.ID, areaController.ID, event.Time, models.SensorTypeBatteryLevel, batteryLevel)
|
||||
logger.Infof("已记录区域主控 (ID: %d) 的电池状态: %+v", areaController.ID, batteryLevel)
|
||||
}
|
||||
|
||||
// handleAckEvent 处理下行确认事件
|
||||
@@ -425,11 +425,11 @@ func (c *ChirpStackListener) handleIntegrationEvent(ctx context.Context, event *
|
||||
}
|
||||
|
||||
// recordSensorData 是一个通用方法,用于将传感器数据存入数据库。
|
||||
// regionalControllerID: 区域主控设备的ID
|
||||
// areaControllerID: 区域主控设备的ID
|
||||
// sensorDeviceID: 实际产生传感器数据的普通设备的ID
|
||||
// sensorType: 传感器值的类型 (例如 models.SensorTypeTemperature)
|
||||
// data: 具体的传感器数据结构体实例 (例如 models.TemperatureData)
|
||||
func (c *ChirpStackListener) recordSensorData(ctx context.Context, regionalControllerID uint, sensorDeviceID uint, eventTime time.Time, sensorType models.SensorType, data interface{}) {
|
||||
func (c *ChirpStackListener) recordSensorData(ctx context.Context, areaControllerID uint, sensorDeviceID uint, eventTime time.Time, sensorType models.SensorType, data interface{}) {
|
||||
reqCtx, logger := logs.Trace(ctx, c.ctx, "recordSensorData")
|
||||
// 1. 将传入的结构体序列化为 JSON
|
||||
jsonData, err := json.Marshal(data)
|
||||
@@ -442,7 +442,7 @@ func (c *ChirpStackListener) recordSensorData(ctx context.Context, regionalContr
|
||||
sensorData := &models.SensorData{
|
||||
Time: eventTime,
|
||||
DeviceID: sensorDeviceID,
|
||||
RegionalControllerID: regionalControllerID,
|
||||
AreaControllerID: areaControllerID,
|
||||
SensorType: sensorType,
|
||||
Data: datatypes.JSON(jsonData),
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ type Service interface {
|
||||
Switch(ctx context.Context, device *models.Device, action DeviceAction) error
|
||||
|
||||
// Collect 用于发起对指定区域主控下的多个设备的批量采集请求。
|
||||
Collect(ctx context.Context, regionalControllerID uint, devicesToCollect []*models.Device) error
|
||||
Collect(ctx context.Context, areaControllerID uint, devicesToCollect []*models.Device) error
|
||||
}
|
||||
|
||||
// 设备操作指令通用结构(最外层)
|
||||
|
||||
@@ -133,7 +133,7 @@ func (g *GeneralDeviceService) Switch(ctx context.Context, device *models.Device
|
||||
}
|
||||
|
||||
// Collect 实现了 Service 接口,用于发起对指定区域主控下的多个设备的批量采集请求。
|
||||
func (g *GeneralDeviceService) Collect(ctx context.Context, regionalControllerID uint, devicesToCollect []*models.Device) error {
|
||||
func (g *GeneralDeviceService) Collect(ctx context.Context, areaControllerID uint, devicesToCollect []*models.Device) error {
|
||||
serviceCtx, logger := logs.Trace(ctx, g.ctx, "Collect")
|
||||
if len(devicesToCollect) == 0 {
|
||||
logger.Info("待采集设备列表为空,无需执行采集任务。")
|
||||
@@ -141,12 +141,12 @@ func (g *GeneralDeviceService) Collect(ctx context.Context, regionalControllerID
|
||||
}
|
||||
|
||||
// 1. 从设备列表中获取预加载的区域主控,并进行校验
|
||||
regionalController := &devicesToCollect[0].AreaController
|
||||
if regionalController.ID != regionalControllerID {
|
||||
return fmt.Errorf("设备列表与指定的区域主控ID (%d) 不匹配", regionalControllerID)
|
||||
areaController := &devicesToCollect[0].AreaController
|
||||
if areaController.ID != areaControllerID {
|
||||
return fmt.Errorf("设备列表与指定的区域主控ID (%d) 不匹配", areaControllerID)
|
||||
}
|
||||
if err := regionalController.SelfCheck(); err != nil {
|
||||
return fmt.Errorf("区域主控 (ID: %d) 未通过自检: %w", regionalControllerID, err)
|
||||
if err := areaController.SelfCheck(); err != nil {
|
||||
return fmt.Errorf("区域主控 (ID: %d) 未通过自检: %w", areaControllerID, err)
|
||||
}
|
||||
|
||||
// 2. 准备采集任务列表
|
||||
@@ -208,13 +208,13 @@ func (g *GeneralDeviceService) Collect(ctx context.Context, regionalControllerID
|
||||
}
|
||||
|
||||
// 3. 构建并发送指令
|
||||
networkID := regionalController.NetworkID
|
||||
networkID := areaController.NetworkID
|
||||
|
||||
// 4. 创建待处理请求记录
|
||||
correlationID := uuid.New().String()
|
||||
pendingReq := &models.PendingCollection{
|
||||
CorrelationID: correlationID,
|
||||
DeviceID: regionalController.ID,
|
||||
DeviceID: areaController.ID,
|
||||
CommandMetadata: childDeviceIDs,
|
||||
Status: models.PendingStatusPending,
|
||||
CreatedAt: time.Now(),
|
||||
@@ -223,7 +223,7 @@ func (g *GeneralDeviceService) Collect(ctx context.Context, regionalControllerID
|
||||
logger.Errorf("创建待采集请求失败 (CorrelationID: %s): %v", correlationID, err)
|
||||
return err
|
||||
}
|
||||
logger.Infof("成功创建待采集请求 (CorrelationID: %s, DeviceID: %d)", correlationID, regionalController.ID)
|
||||
logger.Infof("成功创建待采集请求 (CorrelationID: %s, DeviceID: %d)", correlationID, areaController.ID)
|
||||
|
||||
// 5. 构建最终的空中载荷
|
||||
batchCmd := &proto.BatchCollectCommand{
|
||||
|
||||
@@ -57,8 +57,8 @@ type SensorData struct {
|
||||
// DeviceID 是传感器的唯一标识符,作为复合主键的另一部分。
|
||||
DeviceID uint `gorm:"primaryKey" json:"device_id"`
|
||||
|
||||
// RegionalControllerID 是上报此数据的区域主控的ID。
|
||||
RegionalControllerID uint `json:"regional_controller_id"`
|
||||
// AreaControllerID 是上报此数据的区域主控的ID。
|
||||
AreaControllerID uint `json:"area_controller_id"`
|
||||
|
||||
// SensorType 是传感数据的类型
|
||||
SensorType SensorType `gorm:"not null;index" json:"sensor_type"`
|
||||
|
||||
@@ -406,13 +406,13 @@ func (t *LoRaMeshUartPassthroughTransport) handleUpstreamMessage(ctx context.Con
|
||||
logger.Infof("成功解析采集响应 (CorrelationID: %s),包含 %d 个值。", correlationID, len(collectResp.Values))
|
||||
|
||||
// 3. 查找区域主控 (注意:LoRa Mesh 的 SourceAddr 对应于区域主控的 NetworkID)
|
||||
regionalController, err := t.areaControllerRepo.FindByNetworkID(loraCtx, msg.SourceAddr)
|
||||
areaController, err := t.areaControllerRepo.FindByNetworkID(loraCtx, msg.SourceAddr)
|
||||
if err != nil {
|
||||
logger.Errorf("处理上行消息失败:无法通过源地址 '%s' 找到区域主控设备: %v", msg.SourceAddr, err)
|
||||
return
|
||||
}
|
||||
if err := regionalController.SelfCheck(); err != nil {
|
||||
logger.Errorf("处理上行消息失败:区域主控 %v(ID: %d) 未通过自检: %v", regionalController.Name, regionalController.ID, err)
|
||||
if err := areaController.SelfCheck(); err != nil {
|
||||
logger.Errorf("处理上行消息失败:区域主控 %v(ID: %d) 未通过自检: %v", areaController.Name, areaController.ID, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -489,7 +489,7 @@ func (t *LoRaMeshUartPassthroughTransport) handleUpstreamMessage(ctx context.Con
|
||||
dataToRecord = map[string]float64{"value": parsedValue}
|
||||
}
|
||||
|
||||
t.recordSensorData(loraCtx, regionalController.ID, dev.ID, time.Now(), valueDescriptor.Type, dataToRecord)
|
||||
t.recordSensorData(loraCtx, areaController.ID, dev.ID, time.Now(), valueDescriptor.Type, dataToRecord)
|
||||
logger.Infof("成功记录传感器数据: 设备ID=%d, 类型=%s, 原始值=%f, 解析值=%.2f", dev.ID, valueDescriptor.Type, rawSensorValue, parsedValue)
|
||||
}
|
||||
|
||||
@@ -502,7 +502,7 @@ func (t *LoRaMeshUartPassthroughTransport) handleUpstreamMessage(ctx context.Con
|
||||
}
|
||||
|
||||
// recordSensorData 是一个通用方法,用于将传感器数据存入数据库。
|
||||
func (t *LoRaMeshUartPassthroughTransport) recordSensorData(ctx context.Context, regionalControllerID uint, sensorDeviceID uint, eventTime time.Time, sensorType models.SensorType, data interface{}) {
|
||||
func (t *LoRaMeshUartPassthroughTransport) recordSensorData(ctx context.Context, areaControllerID uint, sensorDeviceID uint, eventTime time.Time, sensorType models.SensorType, data interface{}) {
|
||||
loraCtx, logger := logs.Trace(ctx, t.ctx, "recordSensorData")
|
||||
|
||||
jsonData, err := json.Marshal(data)
|
||||
@@ -514,7 +514,7 @@ func (t *LoRaMeshUartPassthroughTransport) recordSensorData(ctx context.Context,
|
||||
sensorData := &models.SensorData{
|
||||
Time: eventTime,
|
||||
DeviceID: sensorDeviceID,
|
||||
RegionalControllerID: regionalControllerID,
|
||||
AreaControllerID: areaControllerID,
|
||||
SensorType: sensorType,
|
||||
Data: datatypes.JSON(jsonData),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user