141 lines
3.9 KiB
Go
141 lines
3.9 KiB
Go
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
|
||
}
|