2025-12-10 14:24:36 +08:00

141 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package business
import (
"fmt"
"strconv"
"time"
"Dynamic_environmental_detection/logger"
)
type SensorData struct {
DeviceUUID string
TaskID string
Address string
SensorType SensorType
Facility string
RawData []byte
Timestamp time.Time
Error error
}
// DataCollector 数据采集器
type DataCollector struct {
modbusConfig *ModbusConfig
lastReadTime time.Time
}
// NewDataCollector 创建数据采集器
func NewDataCollector(config *ModbusConfig) *DataCollector {
return &DataCollector{
modbusConfig: config,
lastReadTime: time.Now().Add(-config.SensorInterval),
}
}
// ReadSensorData 读取单个传感器数据使用新的Modbus客户端
func (dc *DataCollector) ReadSensorData(sensorConfig SensorConfig) (*SensorData, error) {
dc.ensureCommunicationInterval()
// 获取寄存器配置(只包含地址和数量)
registerConfig, err := GetRegisterConfig(sensorConfig.GetSensorType())
if err != nil {
return nil, fmt.Errorf("Failed to get register configuration: %v", err)
}
slaveID, err := strconv.Atoi(sensorConfig.Facility)
if err != nil || slaveID < 1 || slaveID > 247 {
return nil, fmt.Errorf("Invalid facility value, cannot be used as SlaveID: %s (DeviceUUID: %s)",
sensorConfig.Facility, sensorConfig.DeviceUUID)
}
slaveIDByte := byte(slaveID)
logger.Logger.Printf("Reading sensor data - Device: %s, SlaveID: %d (from facility=%s), Addr: %d, Count: %d",
sensorConfig.DeviceUUID, slaveID, sensorConfig.Facility,
registerConfig.RegisterAddress, registerConfig.RegisterCount)
client, err := NewDebugModbusClient(dc.modbusConfig, slaveIDByte)
if err != nil {
return nil, fmt.Errorf("Failed to create Modbus client: %v", err)
}
defer client.Close()
rawData, err := client.ReadHoldingRegisters(
registerConfig.RegisterAddress,
registerConfig.RegisterCount,
)
if err != nil {
return nil, fmt.Errorf("Failed to read sensor data (DeviceUUID: %s): %v",
sensorConfig.DeviceUUID, err)
}
sensorData := &SensorData{
DeviceUUID: sensorConfig.DeviceUUID,
TaskID: sensorConfig.TaskID,
Address: sensorConfig.Address,
SensorType: sensorConfig.GetSensorType(),
Facility: sensorConfig.Facility,
RawData: rawData,
Timestamp: time.Now(),
}
// 成功日志也用真实的 slaveID
logger.Logger.Printf("Successfully read sensor data - DeviceUUID: %s, SlaveID: %d (from facility=%s), RawData: %v",
sensorConfig.DeviceUUID, slaveID, sensorConfig.Facility, rawData)
// 更新最后读取时间
dc.lastReadTime = time.Now()
return sensorData, nil
}
// 确保通信间隔
func (dc *DataCollector) ensureCommunicationInterval() {
elapsed := time.Since(dc.lastReadTime)
if elapsed < dc.modbusConfig.SensorInterval {
sleepTime := dc.modbusConfig.SensorInterval - elapsed
logger.Logger.Printf("Waiting for 485 communication interval: %v", sleepTime)
time.Sleep(sleepTime)
}
}
// 批量读取所有传感器数据
func (dc *DataCollector) BatchReadSensorData(sensorConfigs []SensorConfig) ([]*SensorData, []error) {
var results []*SensorData
var errors []error
// 按传感器类型分组,优化读取顺序
groupedConfigs := groupSensorsByType(sensorConfigs)
for _, configs := range groupedConfigs {
for _, config := range configs {
sensorData, err := dc.ReadSensorData(config)
if err != nil {
errors = append(errors, err)
if len(errors) > 2 {
logger.Logger.Printf("Detected consecutive communication errors, increasing bus stabilization time")
time.Sleep(dc.modbusConfig.BusResetDelay * 2)
}
continue
}
results = append(results, sensorData)
}
}
return results, errors
}
// 按传感器类型分组
func groupSensorsByType(configs []SensorConfig) map[SensorType][]SensorConfig {
groups := make(map[SensorType][]SensorConfig)
for _, config := range configs {
sensorType := config.GetSensorType()
groups[sensorType] = append(groups[sensorType], config)
}
return groups
}