From da2e0f6c9921f538357a08259ae1e544b63e3500 Mon Sep 17 00:00:00 2001 From: fengyarnom Date: Thu, 15 May 2025 18:45:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E1=E5=88=86=E9=92=9F?= =?UTF-8?q?=E7=9A=84=E7=B2=92=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/dao/sensor.go | 30 ++++++++++ internal/handler/sensor.go | 55 +++++++++++++++++ main.go | 1 + static/index.html | 120 ++++++++++++++++++++++++++++++++++++- 4 files changed, 204 insertions(+), 2 deletions(-) diff --git a/internal/dao/sensor.go b/internal/dao/sensor.go index 07a0743..220b2ab 100644 --- a/internal/dao/sensor.go +++ b/internal/dao/sensor.go @@ -219,3 +219,33 @@ func findNearestPoint(t time.Time, timestamps []int64, dataMap map[int64]model.A return dataMap[nearest] } + +// GetLatestSensorData 获取最新的一条传感器数据 +func (dao *SensorDAO) GetLatestSensorData() (*model.SensorData, error) { + query := ` + SELECT id, timestamp, wind_speed, wind_force, wind_direction_8, + wind_direction_360, humidity, temperature, atm_pressure, + solar_radiation, rainfall + FROM sensor_data + ORDER BY timestamp DESC + LIMIT 1 + ` + + var data model.SensorData + err := dao.db.QueryRow(query).Scan( + &data.ID, &data.Timestamp, &data.WindSpeed, &data.WindForce, &data.WindDirection8, + &data.WindDirection360, &data.Humidity, &data.Temperature, &data.AtmPressure, + &data.SolarRadiation, &data.Rainfall, + ) + + if err != nil { + if err == sql.ErrNoRows { + logger.Logger.Printf("未找到传感器数据") + return nil, nil + } + logger.Logger.Printf("获取最新传感器数据失败: %v", err) + return nil, err + } + + return &data, nil +} diff --git a/internal/handler/sensor.go b/internal/handler/sensor.go index d5c86a2..eda30a6 100644 --- a/internal/handler/sensor.go +++ b/internal/handler/sensor.go @@ -128,3 +128,58 @@ func (h *SensorHandler) GetLatestData(w http.ResponseWriter, r *http.Request) { return } } + +// GetLatestSensorRawData 获取最新的一条传感器原始数据 +func (h *SensorHandler) GetLatestSensorRawData(w http.ResponseWriter, r *http.Request) { + data, err := h.dao.GetLatestSensorData() + if err != nil { + logger.Logger.Printf("获取最新传感器数据失败: %v", err) + http.Error(w, "服务器内部错误", http.StatusInternalServerError) + return + } + + if data == nil { + // 没有数据,返回空对象 + w.Header().Set("Content-Type", "application/json") + w.Write([]byte("{}")) + return + } + + // 转换为前端友好的格式 + response := struct { + ID int64 `json:"id"` + Timestamp time.Time `json:"timestamp"` + FormattedTime string `json:"formatted_time"` + WindSpeed float64 `json:"wind_speed"` // 风速(m/s) + WindForce int `json:"wind_force"` // 风力(级) + WindDirection8 int `json:"wind_direction_8"` // 8方位风向 + WindDirection360 int `json:"wind_direction_360"` // 360度风向 + Humidity float64 `json:"humidity"` // 湿度(%) + Temperature float64 `json:"temperature"` // 温度(℃) + AtmPressure float64 `json:"atm_pressure"` // 大气压(kPa) + SolarRadiation int `json:"solar_radiation"` // 太阳辐射(W/m²) + Rainfall int `json:"rainfall"` // 累计雨量(mm) + }{ + ID: data.ID, + Timestamp: data.Timestamp, + FormattedTime: data.Timestamp.Format("2006-01-02 15:04:05"), + WindSpeed: float64(data.WindSpeed) / 100.0, + WindForce: data.WindForce, + WindDirection8: data.WindDirection8, + WindDirection360: data.WindDirection360, + Humidity: float64(data.Humidity) / 10.0, + Temperature: float64(data.Temperature) / 10.0, + AtmPressure: float64(data.AtmPressure) / 10.0, + SolarRadiation: data.SolarRadiation, + Rainfall: data.Rainfall, + } + + w.Header().Set("Content-Type", "application/json") + encoder := json.NewEncoder(w) + encoder.SetIndent("", " ") + if err := encoder.Encode(response); err != nil { + logger.Logger.Printf("JSON编码失败: %v", err) + http.Error(w, "服务器内部错误", http.StatusInternalServerError) + return + } +} diff --git a/main.go b/main.go index 6df05a0..e62843b 100644 --- a/main.go +++ b/main.go @@ -54,6 +54,7 @@ func main() { http.HandleFunc("/api/data", sensorHandler.GetAggregatedData) http.HandleFunc("/api/latest", sensorHandler.GetLatestData) http.HandleFunc("/api/status", sensorHandler.GetConnectionStatus) + http.HandleFunc("/api/raw/latest", sensorHandler.GetLatestSensorRawData) http.HandleFunc("/", sensorHandler.ServeStatic) // 启动TCP服务器 diff --git a/static/index.html b/static/index.html index 97a7a7a..315e487 100644 --- a/static/index.html +++ b/static/index.html @@ -41,6 +41,49 @@ gap: 5px; } + .latest-data { + margin-bottom: 20px; + padding: 15px; + border: 1px solid #ddd; + border-radius: 4px; + background-color: #f8f9fa; + } + + .latest-data h3 { + margin-top: 0; + margin-bottom: 10px; + color: #333; + } + + .data-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 10px; + } + + .data-item { + padding: 8px; + border: 1px solid #eee; + border-radius: 4px; + background-color: white; + } + + .data-label { + font-weight: bold; + color: #555; + font-size: 12px; + } + + .data-value { + font-size: 18px; + color: #007bff; + } + + .data-unit { + font-size: 12px; + color: #777; + } + select, input, button { padding: 5px 10px; border: 1px solid #ddd; @@ -128,7 +171,7 @@
-
@@ -153,6 +195,48 @@
+ +
+

最新传感器数据

+
+
+
温度
+
--
+
+
+
+
湿度
+
--
+
%
+
+
+
风速
+
--
+
m/s
+
+
+
风向
+
--
+
°
+
+
+
大气压
+
--
+
kPa
+
+
+
太阳辐射
+
--
+
W/m²
+
+
+
累计雨量
+
--
+
mm
+
+
+
+
@@ -252,6 +336,31 @@ }); } + // 获取最新传感器数据 + function fetchLatestSensorData() { + fetch('/api/raw/latest') + .then(response => response.json()) + .then(data => { + if (!data || !data.timestamp) { + console.log('No latest sensor data available'); + return; + } + + // 更新最新数据显示 + document.getElementById('latest-time').textContent = `(${data.formatted_time})`; + document.getElementById('latest-temperature').textContent = data.temperature.toFixed(1); + document.getElementById('latest-humidity').textContent = data.humidity.toFixed(1); + document.getElementById('latest-wind-speed').textContent = data.wind_speed.toFixed(2); + document.getElementById('latest-wind-direction').textContent = data.wind_direction_360; + document.getElementById('latest-atm-pressure').textContent = data.atm_pressure.toFixed(1); + document.getElementById('latest-solar-radiation').textContent = data.solar_radiation; + document.getElementById('latest-rainfall').textContent = data.rainfall; + }) + .catch(error => { + console.error('获取最新传感器数据失败:', error); + }); + } + // 查询最新数据 function queryLatestData() { const interval = document.getElementById('interval').value; @@ -280,6 +389,9 @@ // 加载状态指示 document.getElementById('mainChart').style.opacity = 0.5; + // 同时获取最新的传感器原始数据 + fetchLatestSensorData(); + fetch(`/api/latest?interval=${interval}&start=${startDateTime}&end=${endDateTime}`) .then(response => response.json()) .then(data => { @@ -480,10 +592,14 @@ document.addEventListener('DOMContentLoaded', function() { initDatePickers(); queryLatestData(); // 初始加载最新数据 + fetchLatestSensorData(); // 获取最新传感器原始数据 // 每30秒检查一次连接状态 checkConnectionStatus(); connectionCheckTimer = setInterval(checkConnectionStatus, 30000); + + // 每分钟自动刷新最新传感器数据 + setInterval(fetchLatestSensorData, 60000); }); // 页面卸载时清除定时器