feat: 新的解析函数

This commit is contained in:
fengyarnom 2025-05-24 13:13:57 +08:00
parent 07b5cb9843
commit a2d0bc8226
4 changed files with 335 additions and 271 deletions

28
db.go
View File

@ -48,20 +48,22 @@ func CloseDB() {
} }
} }
// 保存传感器数据 - 将浮点值转换为整数存储 // 保存传感器数据 - 将浮点值转换为整数存储,添加温度支持
func SaveSensorData(sensorID int, x, y, z float64) error { func SaveSensorData(sensorID int, x, y, z, temperature float64) error {
xInt := int(x * SCALING_FACTOR) xInt := int(x * SCALING_FACTOR)
yInt := int(y * SCALING_FACTOR) yInt := int(y * SCALING_FACTOR)
zInt := int(z * SCALING_FACTOR) zInt := int(z * SCALING_FACTOR)
tempInt := int(temperature * SCALING_FACTOR)
query := `INSERT INTO sensor_data (sensor_id, x_value, y_value, z_value) VALUES (?, ?, ?, ?)` query := `INSERT INTO sensor_data (sensor_id, x_value, y_value, z_value, temperature) VALUES (?, ?, ?, ?, ?)`
_, err := db.Exec(query, sensorID, xInt, yInt, zInt) _, err := db.Exec(query, sensorID, xInt, yInt, zInt, tempInt)
return err return err
} }
// 获取传感器数据 - 添加时间范围 // 获取传感器数据 - 添加时间范围,包含温度字段
func GetSensorData(sensorID int, limit int, startDate time.Time, endDate time.Time) ([]SensorData, error) { func GetSensorData(sensorID int, limit int, startDate time.Time, endDate time.Time) ([]SensorData, error) {
query := `SELECT id, sensor_id, x_value, y_value, z_value, query := `SELECT id, sensor_id, x_value, y_value, z_value,
COALESCE(temperature, 0) as temperature,
timestamp as timestamp timestamp as timestamp
FROM sensor_data FROM sensor_data
WHERE sensor_id = ?` WHERE sensor_id = ?`
@ -97,9 +99,9 @@ func GetSensorData(sensorID int, limit int, startDate time.Time, endDate time.Ti
for rows.Next() { for rows.Next() {
var data SensorData var data SensorData
var xInt, yInt, zInt int var xInt, yInt, zInt, tempInt int
err := rows.Scan(&data.ID, &data.SensorID, &xInt, &yInt, &zInt, &data.Timestamp) err := rows.Scan(&data.ID, &data.SensorID, &xInt, &yInt, &zInt, &tempInt, &data.Timestamp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -107,6 +109,7 @@ func GetSensorData(sensorID int, limit int, startDate time.Time, endDate time.Ti
data.X = float64(xInt) / SCALING_FACTOR data.X = float64(xInt) / SCALING_FACTOR
data.Y = float64(yInt) / SCALING_FACTOR data.Y = float64(yInt) / SCALING_FACTOR
data.Z = float64(zInt) / SCALING_FACTOR data.Z = float64(zInt) / SCALING_FACTOR
data.Temperature = float64(tempInt) / SCALING_FACTOR
result = append(result, data) result = append(result, data)
} }
@ -114,9 +117,10 @@ func GetSensorData(sensorID int, limit int, startDate time.Time, endDate time.Ti
return result, nil return result, nil
} }
// 获取所有传感器数据 // 获取所有传感器数据,包含温度字段
func GetAllSensorData(limit int, startDate time.Time, endDate time.Time) ([]SensorData, error) { func GetAllSensorData(limit int, startDate time.Time, endDate time.Time) ([]SensorData, error) {
query := `SELECT id, sensor_id, x_value, y_value, z_value, query := `SELECT id, sensor_id, x_value, y_value, z_value,
COALESCE(temperature, 0) as temperature,
timestamp as timestamp timestamp as timestamp
FROM sensor_data FROM sensor_data
WHERE 1=1` WHERE 1=1`
@ -151,9 +155,9 @@ func GetAllSensorData(limit int, startDate time.Time, endDate time.Time) ([]Sens
for rows.Next() { for rows.Next() {
var data SensorData var data SensorData
var xInt, yInt, zInt int var xInt, yInt, zInt, tempInt int
err := rows.Scan(&data.ID, &data.SensorID, &xInt, &yInt, &zInt, &data.Timestamp) err := rows.Scan(&data.ID, &data.SensorID, &xInt, &yInt, &zInt, &tempInt, &data.Timestamp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -161,6 +165,7 @@ func GetAllSensorData(limit int, startDate time.Time, endDate time.Time) ([]Sens
data.X = float64(xInt) / SCALING_FACTOR data.X = float64(xInt) / SCALING_FACTOR
data.Y = float64(yInt) / SCALING_FACTOR data.Y = float64(yInt) / SCALING_FACTOR
data.Z = float64(zInt) / SCALING_FACTOR data.Z = float64(zInt) / SCALING_FACTOR
data.Temperature = float64(tempInt) / SCALING_FACTOR
result = append(result, data) result = append(result, data)
} }
@ -190,12 +195,13 @@ func GetAllSensorIDs() ([]int, error) {
return ids, nil return ids, nil
} }
// SensorData 结构用于存储传感器数据 // SensorData 结构用于存储传感器数据,添加温度字段
type SensorData struct { type SensorData struct {
ID int `json:"id"` ID int `json:"id"`
SensorID int `json:"sensor_id"` SensorID int `json:"sensor_id"`
X float64 `json:"x"` X float64 `json:"x"`
Y float64 `json:"y"` Y float64 `json:"y"`
Z float64 `json:"z"` Z float64 `json:"z"`
Temperature float64 `json:"temperature"`
Timestamp time.Time `json:"timestamp"` Timestamp time.Time `json:"timestamp"`
} }

View File

@ -55,6 +55,9 @@ func handleConnection(conn net.Conn) {
addClient(remoteAddr) addClient(remoteAddr)
// 启动定时发送指令的goroutine
go sendPeriodicCommand(conn, remoteAddr)
buffer := make([]byte, 1024) buffer := make([]byte, 1024)
for { for {
@ -72,13 +75,13 @@ func handleConnection(conn net.Conn) {
rawData := string(buffer[:n]) rawData := string(buffer[:n])
TCPDataLogger.Printf("从客户端 %s 接收到原始数据: %s", remoteAddr, rawData) TCPDataLogger.Printf("从客户端 %s 接收到原始数据: %s", remoteAddr, rawData)
sensorID, x, y, z, err := parseData(rawData) sensorID, x, y, z, temperature, err := parseData(rawData)
if err == nil { if err == nil {
TCPDataLogger.Printf("解析成功 - 客户端: %s, 传感器ID: %d, 值: X=%.3f, Y=%.3f, Z=%.3f", TCPDataLogger.Printf("解析成功 - 客户端: %s, 传感器ID: %d, 值: X=%.3f, Y=%.3f, Z=%.3f, 温度=%.1f°C",
remoteAddr, sensorID, x, y, z) remoteAddr, sensorID, x, y, z, temperature)
if err := SaveSensorData(sensorID, x, y, z); err != nil { if err := SaveSensorData(sensorID, x, y, z, temperature); err != nil {
Logger.Printf("保存传感器数据失败: %v", err) Logger.Printf("保存传感器数据失败: %v", err)
} }
} else { } else {
@ -96,36 +99,89 @@ func handleConnection(conn net.Conn) {
} }
} }
// parseData 使用正则表达式解析传感器数据 // sendPeriodicCommand 每10秒发送一次查询指令
func parseData(data string) (int, float64, float64, float64, error) { func sendPeriodicCommand(conn net.Conn, remoteAddr string) {
pattern := regexp.MustCompile(`(\d+):([-]?\d+\.\d+),\s*([-]?\d+\.\d+),\s*([-]?\d+\.\d+)`) ticker := time.NewTicker(10 * time.Second)
matches := pattern.FindStringSubmatch(data) defer ticker.Stop()
if len(matches) != 5 { for {
return 0, 0, 0, 0, fmt.Errorf("数据格式不正确: %s", data) select {
case <-ticker.C:
command := "@1602301014A*0!\n"
if _, err := conn.Write([]byte(command)); err != nil {
Logger.Printf("发送定时指令到客户端 %s 失败: %v", remoteAddr, err)
return // 连接断开退出goroutine
}
TCPDataLogger.Printf("发送定时指令到客户端 %s: %s", remoteAddr, strings.TrimSpace(command))
}
}
}
// parseData 使用正则表达式解析传感器数据,支持新格式 #{1602301014-01,1,1,28.4,-6.884,1.540}!
func parseData(data string) (int, float64, float64, float64, float64, error) {
// 尝试解析新格式: #{1602301014-01,1,1,28.4,-6.884,1.540}!
newPattern := regexp.MustCompile(`#\{[^,]+-(\d+),\d+,(\d+),([-]?\d+\.\d+),([-]?\d+\.\d+),([-]?\d+\.\d+)\}!`)
matches := newPattern.FindStringSubmatch(data)
if len(matches) == 6 {
// 新格式解析
sensorID, err := strconv.Atoi(matches[2]) // 使用传感器地址编号
if err != nil {
return 0, 0, 0, 0, 0, fmt.Errorf("解析传感器ID失败: %v", err)
} }
temperature, err := strconv.ParseFloat(strings.TrimSpace(matches[3]), 64)
if err != nil {
return 0, 0, 0, 0, 0, fmt.Errorf("解析温度值失败: %v", err)
}
x, err := strconv.ParseFloat(strings.TrimSpace(matches[4]), 64)
if err != nil {
return 0, 0, 0, 0, 0, fmt.Errorf("解析X值失败: %v", err)
}
y, err := strconv.ParseFloat(strings.TrimSpace(matches[5]), 64)
if err != nil {
return 0, 0, 0, 0, 0, fmt.Errorf("解析Y值失败: %v", err)
}
z := 0.0 // 新格式没有Z值设为0
return sensorID, x, y, z, temperature, nil
}
// 尝试解析旧格式: 1:1.000, 2.000, 3.000
oldPattern := regexp.MustCompile(`(\d+):([-]?\d+\.\d+),\s*([-]?\d+\.\d+),\s*([-]?\d+\.\d+)`)
matches = oldPattern.FindStringSubmatch(data)
if len(matches) == 5 {
// 旧格式解析
sensorID, err := strconv.Atoi(matches[1]) sensorID, err := strconv.Atoi(matches[1])
if err != nil { if err != nil {
return 0, 0, 0, 0, fmt.Errorf("解析传感器ID失败: %v", err) return 0, 0, 0, 0, 0, fmt.Errorf("解析传感器ID失败: %v", err)
} }
x, err := strconv.ParseFloat(strings.TrimSpace(matches[2]), 64) x, err := strconv.ParseFloat(strings.TrimSpace(matches[2]), 64)
if err != nil { if err != nil {
return 0, 0, 0, 0, fmt.Errorf("解析X值失败: %v", err) return 0, 0, 0, 0, 0, fmt.Errorf("解析X值失败: %v", err)
} }
y, err := strconv.ParseFloat(strings.TrimSpace(matches[3]), 64) y, err := strconv.ParseFloat(strings.TrimSpace(matches[3]), 64)
if err != nil { if err != nil {
return 0, 0, 0, 0, fmt.Errorf("解析Y值失败: %v", err) return 0, 0, 0, 0, 0, fmt.Errorf("解析Y值失败: %v", err)
} }
z, err := strconv.ParseFloat(strings.TrimSpace(matches[4]), 64) z, err := strconv.ParseFloat(strings.TrimSpace(matches[4]), 64)
if err != nil { if err != nil {
return 0, 0, 0, 0, fmt.Errorf("解析Z值失败: %v", err) return 0, 0, 0, 0, 0, fmt.Errorf("解析Z值失败: %v", err)
} }
return sensorID, x, y, z, nil temperature := 0.0 // 旧格式没有温度值设为0
return sensorID, x, y, z, temperature, nil
}
return 0, 0, 0, 0, 0, fmt.Errorf("数据格式不正确: %s", data)
} }
// addClient 添加客户端 // addClient 添加客户端

View File

@ -206,6 +206,7 @@
<th>X</th> <th>X</th>
<th>Y</th> <th>Y</th>
<th>Z</th> <th>Z</th>
<th>温度(°C)</th>
</tr> </tr>
</thead> </thead>
<tbody id="tableBody"> <tbody id="tableBody">
@ -439,7 +440,7 @@
if (data.length === 0) { if (data.length === 0) {
const row = document.createElement('tr'); const row = document.createElement('tr');
row.innerHTML = '<td colspan="6" style="text-align: center;">没有数据</td>'; row.innerHTML = '<td colspan="7" style="text-align: center;">没有数据</td>';
tableBody.appendChild(row); tableBody.appendChild(row);
return; return;
} }
@ -467,7 +468,8 @@
'<td>' + formattedDate + '</td>' + '<td>' + formattedDate + '</td>' +
'<td>' + item.x.toFixed(3) + '</td>' + '<td>' + item.x.toFixed(3) + '</td>' +
'<td>' + item.y.toFixed(3) + '</td>' + '<td>' + item.y.toFixed(3) + '</td>' +
'<td>' + item.z.toFixed(3) + '</td>' ; '<td>' + item.z.toFixed(3) + '</td>' +
'<td>' + item.temperature.toFixed(1) + '</td>';
tableBody.appendChild(row); tableBody.appendChild(row);
}); });
@ -579,11 +581,12 @@
'rgb(255, 159, 64)' 'rgb(255, 159, 64)'
]; ];
// 为X, Y, Z创建不同的数据集 // 为X, Y, Z, 温度创建不同的数据集
const dataTypes = [ const dataTypes = [
{ key: 'x', label: 'X' }, { key: 'x', label: 'X' },
{ key: 'y', label: 'Y' }, { key: 'y', label: 'Y' },
{ key: 'z', label: 'Z' } { key: 'z', label: 'Z' },
{ key: 'temperature', label: '温度(°C)' }
]; ];
sensorIDs.forEach((sensorID, sensorIndex) => { sensorIDs.forEach((sensorID, sensorIndex) => {
@ -616,7 +619,7 @@
} }
// 准备CSV内容 // 准备CSV内容
let csvContent = "数据编号,探头地址编号,X,Y,Z,时间\n"; let csvContent = "数据编号,探头地址编号,X,Y,Z,温度,时间\n";
currentSensorData.forEach(item => { currentSensorData.forEach(item => {
// 解析时间并调整为中国时间 // 解析时间并调整为中国时间
@ -632,13 +635,12 @@
date.getMinutes().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0') + ':' +
date.getSeconds().toString().padStart(2, '0'); date.getSeconds().toString().padStart(2, '0');
// 添加一行数据 csvContent += item.id + "," +
csvContent +=
item.id + "," +
item.sensor_id + "," + item.sensor_id + "," +
item.x.toFixed(3) + "," + item.x.toFixed(3) + "," +
item.y.toFixed(3) + "," + item.y.toFixed(3) + "," +
item.z.toFixed(3) + "," + item.z.toFixed(3) + "," +
item.temperature.toFixed(1) + "," +
formattedDate + "\n"; formattedDate + "\n";
}); });

View File

@ -44,13 +44,13 @@ func handleUDPPacket(conn *net.UDPConn, addr *net.UDPAddr, data []byte) {
rawData := string(data) rawData := string(data)
TCPDataLogger.Printf("从UDP客户端 %s 接收到原始数据: %s", remoteAddr, rawData) TCPDataLogger.Printf("从UDP客户端 %s 接收到原始数据: %s", remoteAddr, rawData)
sensorID, x, y, z, err := parseData(rawData) sensorID, x, y, z, temperature, err := parseData(rawData)
if err == nil { if err == nil {
TCPDataLogger.Printf("解析成功 - UDP客户端: %s, 传感器ID: %d, 值: X=%.3f, Y=%.3f, Z=%.3f", TCPDataLogger.Printf("解析成功 - UDP客户端: %s, 传感器ID: %d, 值: X=%.3f, Y=%.3f, Z=%.3f, 温度=%.1f°C",
remoteAddr, sensorID, x, y, z) remoteAddr, sensorID, x, y, z, temperature)
if err := SaveSensorData(sensorID, x, y, z); err != nil { if err := SaveSensorData(sensorID, x, y, z, temperature); err != nil {
Logger.Printf("保存传感器数据失败: %v", err) Logger.Printf("保存传感器数据失败: %v", err)
} }
} else { } else {