2025-11-24 18:06:00 +08:00

147 lines
4.2 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)
}
// 关键:直接把 facility 当作 Modbus 从站地址SlaveID
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)
// 日志:用真实的 slaveID来自 facility
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)
// 使用 facility 作为 SlaveID 创建客户端
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
}
// ensureCommunicationInterval 确保通信间隔
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)
}
}
// BatchReadSensorData 批量读取所有传感器数据
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
}
// groupSensorsByType 按传感器类型分组
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
}