package business import ( "Dynamic_environmental_detection/connect" "encoding/json" "fmt" "strconv" "time" "Dynamic_environmental_detection/logger" "github.com/goburrow/modbus" ) // BusinessManager 业务管理器 type BusinessManager struct { modbusClient modbus.Client modbusConfig *ModbusConfig dataCollector *DataCollector dataProcessor *DataProcessor reportManager *ReportManager sensorConfigs []SensorConfig hostUUID string isFirstCollect bool } // NewBusinessManager 创建业务管理器 func NewBusinessManager(sensorConfigs []SensorConfig) (*BusinessManager, error) { if len(sensorConfigs) == 0 { return nil, fmt.Errorf("sensor configuration is empty") } // 从第一个配置获取host_uuid hostUUID := sensorConfigs[0].HostUUID // 创建Modbus配置 modbusConfig := DefaultModbusConfig() // 创建数据采集器、处理器和上报管理器 dataCollector := NewDataCollector(modbusConfig) dataProcessor := NewDataProcessor() reportManager := NewReportManager(hostUUID) logger.Logger.Printf("DEBUG: Business manager created, isFirstCollect initialized to: true") return &BusinessManager{ modbusConfig: modbusConfig, dataCollector: dataCollector, dataProcessor: dataProcessor, reportManager: reportManager, sensorConfigs: sensorConfigs, hostUUID: hostUUID, isFirstCollect: true, // 初始化第一次采集标志 }, nil } // StartDataCollection 启动数据采集和上报 func (bm *BusinessManager) StartDataCollection() error { logger.Logger.Printf("Starting sensor data collection, total sensors: %d", len(bm.sensorConfigs)) startTime := time.Now() // 批量读取传感器数据 sensorDataList, readErrors := bm.dataCollector.BatchReadSensorData(bm.sensorConfigs) // 更新设备状态并上报事件 bm.updateDeviceStatuses(sensorDataList, readErrors) // 批量处理传感器数据 processedDataList, processErrors := bm.dataProcessor.BatchProcessSensorData(sensorDataList) if len(processErrors) > 0 { logger.Logger.Printf("Partial data processing failed, error count: %d", len(processErrors)) for _, err := range processErrors { logger.Logger.Printf("Processing error: %v", err) } } // 添加调试信息,检查是否为第一次采集 logger.Logger.Printf("DEBUG: Is first collection: %v", bm.isFirstCollect) // 如果是第一次采集,上报整体状态 if bm.isFirstCollect { logger.Logger.Printf("DEBUG: Processing first collection status report") bm.reportFirstCollectionStatus(sensorDataList, readErrors, processedDataList) bm.isFirstCollect = false // 标记为已完成第一次采集 logger.Logger.Printf("DEBUG: First collection status report completed, isFirstCollect set to: %v", bm.isFirstCollect) } // 上报指标数据 if len(processedDataList) > 0 { if err := bm.reportManager.ReportMetricData(processedDataList, bm.sensorConfigs); err != nil { logger.Logger.Printf("Failed to report metric data: %v", err) } } // 统计信息 successCount := 0 for _, data := range processedDataList { if bm.dataProcessor.IsDataValid(data) { successCount++ } } totalTime := time.Since(startTime) logger.Logger.Printf("Data collection completed - Success: %d/%d, Read errors: %d, Process errors: %d, Total time: %v", successCount, len(bm.sensorConfigs), len(readErrors), len(processErrors), totalTime) return nil } // updateDeviceStatuses 更新所有设备状态 func (bm *BusinessManager) updateDeviceStatuses(sensorDataList []*SensorData, readErrors []error) { // 创建错误映射表 errorMap := make(map[string]string) for _, err := range readErrors { // 从错误信息中提取deviceUUID(需要根据实际错误格式调整) errorMap["unknown"] = err.Error() } // 更新成功读取的设备状态 for _, sensorData := range sensorDataList { bm.reportManager.UpdateAndReportDeviceStatus( sensorData.DeviceUUID, true, "", sensorData.SensorType, ) } // 更新读取失败的设备状态 for _, config := range bm.sensorConfigs { found := false for _, sensorData := range sensorDataList { if sensorData.DeviceUUID == config.DeviceUUID { found = true break } } if !found { // 设备读取失败 errMsg := "Device read timeout or communication failure" if len(readErrors) > 0 { errMsg = readErrors[0].Error() } bm.reportManager.UpdateAndReportDeviceStatus( config.DeviceUUID, false, errMsg, config.GetSensorType(), ) } } } // reportFirstCollectionStatus 上报第一次采集的系统状态 // reportFirstCollectionStatus 上报第一次采集的系统状态(新协议:批量发送所有在线设备的 online 事件) func (bm *BusinessManager) reportFirstCollectionStatus(_ []*SensorData, _ []error, processedDataList []*ProcessedSensorData) { // 只使用 processedDataList 就够了,另外两个参数我们不需要但必须保留(调用方传了),用 _ 忽略 successCount := len(processedDataList) totalCount := len(bm.sensorConfigs) logger.Logger.Printf("=== System First Collection Status Report ===") logger.Logger.Printf("Total devices: %d, Successfully collected and processed: %d", totalCount, successCount) // 收集成功设备的 UUID successUUIDs := make([]string, 0, successCount) for _, data := range processedDataList { successUUIDs = append(successUUIDs, data.DeviceUUID) } // 统一时间戳 timestamp := strconv.FormatInt(time.Now().Unix(), 10) // 事件数组 var events []map[string]interface{} for _, uuid := range successUUIDs { sensorName := "Unknown Sensor" for _, cfg := range bm.sensorConfigs { if cfg.DeviceUUID == uuid { sensorName = GetSensorTypeName(cfg.GetSensorType()) break } } events = append(events, map[string]interface{}{ "description": "Sensor online", "timestamp": timestamp, "host_uuid": bm.hostUUID, "deviceuuid": uuid, "level": "online", "sensor_type": sensorName, }) } if len(events) == 0 { logger.Logger.Printf("No successful devices in first collection, skipping report") return } metric := map[string]interface{}{ "type": "event", "args": events, // 批量数组! } routeKey := fmt.Sprintf("/dthjjc/device/%s/event", bm.hostUUID) // 打印完整 JSON 方便你看 fullMsg := map[string]interface{}{ "method": "metric_data", "params": map[string]interface{}{ "route_key": routeKey, "metric": metric, }, } if b, err := json.Marshal(fullMsg); err == nil { logger.Logger.Printf("First collection batch online events: %s", string(b)) } // 发送 if err := connect.ReportMetricData(routeKey, metric); err != nil { logger.Logger.Printf("Failed to report first batch online events: %v", err) } else { logger.Logger.Printf("First collection successful, batch reported %d devices online", len(events)) } } func (bm *BusinessManager) GetReportManager() *ReportManager { return bm.reportManager } // Close 关闭资源 func (bm *BusinessManager) Close() { logger.Logger.Printf("Business manager resources released") }