fix:调整是数据显示与数据获取
This commit is contained in:
parent
16615a5029
commit
4a6c6e58ea
@ -67,7 +67,9 @@ func (dao *SensorDAO) GetAggregatedData(start, end time.Time, interval string) (
|
||||
ROUND(AVG(temperature)/10, 1) AS avg_temp,
|
||||
MAX(rainfall) - MIN(rainfall) AS rainfall,
|
||||
ROUND(AVG(humidity)/10, 1) AS avg_humidity,
|
||||
ROUND(AVG(wind_speed)/10, 1) AS avg_wind_speed
|
||||
ROUND(AVG(wind_speed)/10, 1) AS avg_wind_speed,
|
||||
ROUND(AVG(atm_pressure)/10, 1) AS avg_atm_pressure,
|
||||
ROUND(AVG(solar_radiation)/10, 1) AS avg_solar_radiation
|
||||
FROM sensor_data
|
||||
WHERE timestamp BETWEEN ? AND ?
|
||||
GROUP BY bucket_time
|
||||
@ -92,7 +94,7 @@ func (dao *SensorDAO) GetAggregatedData(start, end time.Time, interval string) (
|
||||
var data model.AggregatedData
|
||||
var tsStr string
|
||||
err := rows.Scan(&tsStr, &data.AvgTemperature, &data.Rainfall,
|
||||
&data.AvgHumidity, &data.AvgWindSpeed)
|
||||
&data.AvgHumidity, &data.AvgWindSpeed, &data.AvgAtmPressure, &data.AvgSolarRadiation)
|
||||
if err != nil {
|
||||
logger.Logger.Printf("扫描数据行失败: %v", err)
|
||||
continue
|
||||
|
||||
@ -19,9 +19,11 @@ type SensorData struct {
|
||||
|
||||
// AggregatedData 聚合数据结构
|
||||
type AggregatedData struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
AvgTemperature float64 `json:"avg_temperature"`
|
||||
Rainfall float64 `json:"rainfall"`
|
||||
AvgHumidity float64 `json:"avg_humidity"`
|
||||
AvgWindSpeed float64 `json:"avg_wind_speed"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
AvgTemperature float64 `json:"avg_temperature"`
|
||||
Rainfall float64 `json:"rainfall"`
|
||||
AvgHumidity float64 `json:"avg_humidity"`
|
||||
AvgWindSpeed float64 `json:"avg_wind_speed"`
|
||||
AvgAtmPressure float64 `json:"atm_pressure"` // 平均大气压
|
||||
AvgSolarRadiation float64 `json:"solar_radiation"` // 平均太阳辐射
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ func handleConnection(sensor *SensorComm) {
|
||||
return
|
||||
}
|
||||
|
||||
// 设置定时器,每分钟查询一次
|
||||
// 设置定时器,每5分钟查询一次
|
||||
ticker := time.NewTicker(time.Minute * 5)
|
||||
defer ticker.Stop()
|
||||
|
||||
@ -76,14 +76,28 @@ func handleConnection(sensor *SensorComm) {
|
||||
buffer := make([]byte, 1024)
|
||||
done := make(chan bool)
|
||||
|
||||
// 设置tcp保持活动状态,防止连接断开
|
||||
tcpConn, ok := sensor.conn.(*net.TCPConn)
|
||||
if ok {
|
||||
tcpConn.SetKeepAlive(true)
|
||||
tcpConn.SetKeepAlivePeriod(30 * time.Second)
|
||||
}
|
||||
|
||||
// 处理接收数据的goroutine
|
||||
go func() {
|
||||
for {
|
||||
// 设置读取超时
|
||||
sensor.conn.SetReadDeadline(time.Now().Add(time.Second * 30))
|
||||
// 设置读取超时 - 增加超时时间到10分钟,大于查询间隔
|
||||
sensor.conn.SetReadDeadline(time.Now().Add(10 * time.Minute))
|
||||
|
||||
n, err := sensor.conn.Read(buffer)
|
||||
if err != nil {
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
// 超时错误不一定意味着连接断开,继续等待
|
||||
logger.Logger.Printf("读取超时: %v, 等待下一次查询", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 其他错误才认为连接断开
|
||||
logger.Logger.Printf("读取数据失败: %v", err)
|
||||
done <- true
|
||||
return
|
||||
@ -109,6 +123,7 @@ func handleConnection(sensor *SensorComm) {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
logger.Logger.Printf("定时查询触发 [%s]", sensor.address)
|
||||
if err := sensor.sendQuery(); err != nil {
|
||||
return
|
||||
}
|
||||
@ -174,7 +189,13 @@ func (s *SensorComm) Close() {
|
||||
|
||||
// 启动TCP服务器
|
||||
func StartTCPServer(dao *dao.SensorDAO) error {
|
||||
listener, err := net.Listen("tcp", tcpPort)
|
||||
// 创建TCP监听器并设置TCP选项
|
||||
addr, err := net.ResolveTCPAddr("tcp", tcpPort)
|
||||
if err != nil {
|
||||
return fmt.Errorf("解析TCP地址失败: %v", err)
|
||||
}
|
||||
|
||||
listener, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("启动TCP服务器失败: %v", err)
|
||||
}
|
||||
@ -186,12 +207,17 @@ func StartTCPServer(dao *dao.SensorDAO) error {
|
||||
var mu sync.Mutex
|
||||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
conn, err := listener.AcceptTCP()
|
||||
if err != nil {
|
||||
logger.Logger.Printf("接受连接失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 设置TCP连接选项
|
||||
conn.SetKeepAlive(true)
|
||||
conn.SetKeepAlivePeriod(30 * time.Second)
|
||||
conn.SetLinger(0) // 立即关闭
|
||||
|
||||
mu.Lock()
|
||||
// 关闭旧连接
|
||||
if currentConn != nil {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>气象站数据监控</title>
|
||||
<title>雨量计数据</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
body {
|
||||
@ -16,7 +16,6 @@
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #ddd;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.container {
|
||||
@ -118,7 +117,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>气象站数据监控</h1>
|
||||
<h1>雨量计数据</h1>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
@ -142,6 +141,11 @@
|
||||
<input type="datetime-local" id="endDate">
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="adaptiveScale">自适应范围:</label>
|
||||
<input type="checkbox" id="adaptiveScale">
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<button onclick="queryData()">查询</button>
|
||||
<button onclick="exportData()">导出数据</button>
|
||||
@ -161,6 +165,8 @@
|
||||
<th>平均温度(℃)</th>
|
||||
<th>平均湿度(%)</th>
|
||||
<th>平均风速(m/s)</th>
|
||||
<th>大气压(hPa)</th>
|
||||
<th>太阳辐射(W/m²)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableBody"></tbody>
|
||||
@ -241,6 +247,26 @@
|
||||
date.getMinutes().toString().padStart(2, '0');
|
||||
});
|
||||
|
||||
// 是否使用自适应范围
|
||||
const useAdaptiveScale = document.getElementById('adaptiveScale').checked;
|
||||
|
||||
// 计算降雨量和温度的范围
|
||||
let rainfallMin = 0;
|
||||
let rainfallMax = 50;
|
||||
let tempMin = -10;
|
||||
let tempMax = 40;
|
||||
|
||||
if (useAdaptiveScale && data.length > 0) {
|
||||
// 找出温度的最小值和最大值,并添加一些边距
|
||||
const temps = data.map(item => item.avg_temperature);
|
||||
tempMin = Math.floor(Math.min(...temps) - 5);
|
||||
tempMax = Math.ceil(Math.max(...temps) + 5);
|
||||
|
||||
// 找出降雨量的最大值,并添加一些边距
|
||||
const rainfalls = data.map(item => item.rainfall);
|
||||
rainfallMax = Math.ceil(Math.max(...rainfalls) * 1.2) || 10; // 如果最大值是0,则默认为10
|
||||
}
|
||||
|
||||
mainChart = new Chart(ctx, {
|
||||
data: {
|
||||
labels: labels,
|
||||
@ -282,10 +308,10 @@
|
||||
grid: {
|
||||
drawOnChartArea: false
|
||||
},
|
||||
// 设置降雨量的合理范围
|
||||
min: 0,
|
||||
max: 50, // 根据实际情况可调整
|
||||
suggestedMax: 10
|
||||
// 设置降雨量的范围
|
||||
min: rainfallMin,
|
||||
max: rainfallMax,
|
||||
suggestedMax: Math.min(10, rainfallMax)
|
||||
},
|
||||
'y-temp': {
|
||||
type: 'linear',
|
||||
@ -294,11 +320,11 @@
|
||||
display: true,
|
||||
text: '温度(℃)'
|
||||
},
|
||||
// 设置温度的合理范围
|
||||
min: -10,
|
||||
max: 40,
|
||||
suggestedMin: 0,
|
||||
suggestedMax: 30
|
||||
// 设置温度的范围
|
||||
min: tempMin,
|
||||
max: tempMax,
|
||||
suggestedMin: Math.max(0, tempMin),
|
||||
suggestedMax: Math.min(30, tempMax)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,6 +357,8 @@
|
||||
<td>${item.avg_temperature.toFixed(1)}</td>
|
||||
<td>${item.avg_humidity.toFixed(1)}</td>
|
||||
<td>${item.avg_wind_speed.toFixed(1)}</td>
|
||||
<td>${item.atm_pressure ? (item.atm_pressure/10).toFixed(1) : 'N/A'}</td>
|
||||
<td>${item.solar_radiation ? (item.solar_radiation/10).toFixed(1) : 'N/A'}</td>
|
||||
`;
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
@ -340,7 +368,7 @@
|
||||
function exportData() {
|
||||
// 从表格中获取完整数据
|
||||
const tableRows = document.querySelectorAll('#tableBody tr');
|
||||
let csv = '时间,降雨量(mm),温度(℃),湿度(%),风速(m/s)\n';
|
||||
let csv = '时间,降雨量(mm),温度(℃),湿度(%),风速(m/s),大气压(hPa),太阳辐射(W/m²)\n';
|
||||
|
||||
tableRows.forEach(row => {
|
||||
const cells = row.querySelectorAll('td');
|
||||
@ -349,7 +377,9 @@
|
||||
cells[1].textContent, // 降雨量
|
||||
cells[2].textContent, // 温度
|
||||
cells[3].textContent, // 湿度
|
||||
cells[4].textContent // 风速
|
||||
cells[4].textContent, // 风速
|
||||
cells[5].textContent, // 大气压
|
||||
cells[6].textContent // 太阳辐射
|
||||
];
|
||||
csv += rowData.join(',') + '\n';
|
||||
});
|
||||
@ -357,7 +387,7 @@
|
||||
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = '气象站数据.csv';
|
||||
link.download = '雨量计数据.csv';
|
||||
link.click();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user