angle_dtu/http_server.go
2025-05-24 13:37:49 +08:00

195 lines
5.5 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 main
import (
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"os"
"path/filepath"
"strconv"
"time"
)
// 启动HTTP服务器
func StartHTTPServer(address string) error {
http.HandleFunc("/", handleIndex)
http.HandleFunc("/api/data", handleGetData)
http.HandleFunc("/api/sensors", handleGetSensors)
http.HandleFunc("/api/clients", handleGetClients)
http.HandleFunc("/api/trigger-query", handleTriggerQuery)
fmt.Printf("HTTP服务器已启动正在监听 %s\n", address)
return http.ListenAndServe(address, nil)
}
// 处理主页
func handleIndex(w http.ResponseWriter, r *http.Request) {
log.Printf("接收到主页请求: %s", r.URL.Path)
templatePath := "templates/index.html"
absPath, _ := filepath.Abs(templatePath)
_, err := os.Stat(templatePath)
if os.IsNotExist(err) {
log.Printf("错误: 模板文件不存在: %s", absPath)
http.Error(w, "模板文件不存在", http.StatusInternalServerError)
return
}
tmpl, err := template.ParseFiles(templatePath)
if err != nil {
log.Printf("错误: 无法解析模板: %v", err)
http.Error(w, "无法加载模板:"+err.Error(), http.StatusInternalServerError)
return
}
log.Printf("模板加载成功,开始渲染")
err = tmpl.Execute(w, nil)
if err != nil {
log.Printf("错误: 渲染模板出错: %v", err)
http.Error(w, "渲染模板出错:"+err.Error(), http.StatusInternalServerError)
}
log.Printf("模板渲染完成")
}
// 处理获取传感器数据的API
func handleGetData(w http.ResponseWriter, r *http.Request) {
log.Printf("接收到获取数据请求: %s", r.URL.String())
w.Header().Set("Content-Type", "application/json")
sensorIDStr := r.URL.Query().Get("sensor_id")
limitStr := r.URL.Query().Get("limit")
startDateStr := r.URL.Query().Get("start_date")
endDateStr := r.URL.Query().Get("end_date")
limit := 500 // 默认限制为500条数据
noLimit := false // 是否不限制数据条数
var sensorID int
var err error
if sensorIDStr != "" && sensorIDStr != "all" {
sensorID, err = strconv.Atoi(sensorIDStr)
if err != nil {
log.Printf("错误: 无效的传感器ID: %s", sensorIDStr)
http.Error(w, "无效的传感器ID", http.StatusBadRequest)
return
}
}
if limitStr != "" {
if limitStr == "all" {
noLimit = true
limit = 0 // 设置为0表示不使用LIMIT子句
} else {
limit, err = strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
log.Printf("错误: 无效的记录数限制: %s", limitStr)
http.Error(w, "无效的记录数限制", http.StatusBadRequest)
return
}
}
}
var startDate, endDate time.Time
if startDateStr != "" {
startDate, err = time.Parse("2006-01-02T15:04", startDateStr)
if err != nil {
log.Printf("错误: 无效的开始日期: %s, %v", startDateStr, err)
http.Error(w, "无效的开始日期", http.StatusBadRequest)
return
}
}
if endDateStr != "" {
endDate, err = time.Parse("2006-01-02T15:04", endDateStr)
if err != nil {
log.Printf("错误: 无效的结束日期: %s, %v", endDateStr, err)
http.Error(w, "无效的结束日期", http.StatusBadRequest)
return
}
}
var data []SensorData
if sensorIDStr == "all" || sensorIDStr == "" {
data, err = GetAllSensorData(limit, startDate, endDate)
} else {
data, err = GetSensorData(sensorID, limit, startDate, endDate)
}
if err != nil {
log.Printf("错误: 获取数据失败: %v", err)
http.Error(w, "获取数据失败:"+err.Error(), http.StatusInternalServerError)
return
}
if noLimit {
log.Printf("成功获取到所有数据记录(%d条", len(data))
} else {
log.Printf("成功获取到 %d 条数据记录(限制:%d条", len(data), limit)
}
if err := json.NewEncoder(w).Encode(data); err != nil {
log.Printf("错误: 编码JSON失败: %v", err)
http.Error(w, "编码JSON失败"+err.Error(), http.StatusInternalServerError)
}
}
// 处理获取所有传感器ID的API
func handleGetSensors(w http.ResponseWriter, r *http.Request) {
log.Printf("接收到获取传感器列表请求")
w.Header().Set("Content-Type", "application/json")
sensorIDs, err := GetAllSensorIDs()
if err != nil {
log.Printf("错误: 获取传感器ID失败: %v", err)
http.Error(w, "获取传感器ID失败"+err.Error(), http.StatusInternalServerError)
return
}
log.Printf("成功获取到 %d 个传感器ID", len(sensorIDs))
if err := json.NewEncoder(w).Encode(sensorIDs); err != nil {
log.Printf("错误: 编码JSON失败: %v", err)
http.Error(w, "编码JSON失败"+err.Error(), http.StatusInternalServerError)
}
}
func handleGetClients(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
clients := getAllClients()
if err := json.NewEncoder(w).Encode(clients); err != nil {
log.Printf("错误: 编码客户端信息JSON失败: %v", err)
http.Error(w, "编码JSON失败"+err.Error(), http.StatusInternalServerError)
}
}
// 处理手动触发查询指令的API
func handleTriggerQuery(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != "POST" {
http.Error(w, "只支持POST请求", http.StatusMethodNotAllowed)
return
}
// 触发向所有在线客户端发送查询指令
sent := triggerManualQuery()
response := map[string]interface{}{
"success": true,
"message": fmt.Sprintf("已向%d个客户端发送查询指令", sent),
"sent_count": sent,
}
if err := json.NewEncoder(w).Encode(response); err != nil {
log.Printf("错误: 编码响应JSON失败: %v", err)
http.Error(w, "编码JSON失败"+err.Error(), http.StatusInternalServerError)
}
}