-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandlers.go
More file actions
156 lines (134 loc) · 4.52 KB
/
Copy pathhandlers.go
File metadata and controls
156 lines (134 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package main
import (
"net/http"
"path"
"path/filepath"
"time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// setupRouter configures the HTTP routes
func setupRouter(db *gorm.DB) *gin.Engine {
// Disable Console Color
// gin.DisableConsoleColor()
r := gin.Default()
// Serve frontend static files, the ui directory
r.NoRoute(func(c *gin.Context) {
dir, file := path.Split(c.Request.RequestURI)
ext := filepath.Ext(file)
if file == "" || ext == "" {
c.File("./ui/dist/ui/index.html")
} else {
c.File("./ui/dist/ui/" + path.Join(dir, file))
}
})
// API endpoints
r.GET("/reports/latest", func(c *gin.Context) {
getLatestWeatherReport(c, db)
})
r.GET("/reports/:model", func(c *gin.Context) {
getWeatherReportsByModel(c, db)
})
r.GET("/models", func(c *gin.Context) {
getModels(c, db)
})
r.GET("/recommendations/latest", func(c *gin.Context) {
getLatestRecommendation(c, db)
})
r.GET("/config", func(c *gin.Context) {
getConfig(c)
})
r.POST("/config", func(c *gin.Context) {
updateConfig(c)
})
return r
}
// getLatestWeatherReport handles GET /reports/latest
func getLatestWeatherReport(c *gin.Context, db *gorm.DB) {
var weatherReport WeatherReport
result := db.Order("db_id desc").First(&weatherReport)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve latest weather report"})
return
}
c.JSON(http.StatusOK, weatherReport)
}
// getWeatherReportsByModel handles GET /reports/:model
func getWeatherReportsByModel(c *gin.Context, db *gorm.DB) {
model := c.Param("model")
var weatherReports []WeatherReport
threeDaysAgo := time.Now().AddDate(0, 0, -5)
result := db.Where("device_model = ? AND time > ?", model, threeDaysAgo).Find(&weatherReports)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve weather reports"})
return
}
c.JSON(http.StatusOK, weatherReports)
}
// getModels handles GET /models
func getModels(c *gin.Context, db *gorm.DB) {
var deviceModels []DeviceModelCount
// the device model count is a mix of the device model table and a count of the weather reports, so we need to do a join
result := db.Table("device_models").Select("device_models.device_model, device_models.name, count(weather_reports.device_model) as report_count").Joins("left join weather_reports on device_models.device_model = weather_reports.device_model").Group("device_models.device_model").Find(&deviceModels)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve device models"})
return
}
c.JSON(http.StatusOK, deviceModels)
}
// getLatestRecommendation handles GET /recommendations/latest
func getLatestRecommendation(c *gin.Context, db *gorm.DB) {
var recommendation OllamaRecommendation
result := db.Order("db_id desc").First(&recommendation)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve latest recommendation"})
return
}
c.JSON(http.StatusOK, recommendation)
}
// getConfig handles GET /config
func getConfig(c *gin.Context) {
c.JSON(http.StatusOK, config)
}
// updateConfig handles POST /config
func updateConfig(c *gin.Context) {
var newConfig Config
if err := c.ShouldBindJSON(&newConfig); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON format"})
return
}
// Validate required fields
if newConfig.OpenAIBaseURL == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "OpenAIBaseURL is required"})
return
}
if newConfig.OpenAIModel == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "OpenAIModel is required"})
return
}
if newConfig.IndoorDeviceModel == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "IndoorDeviceModel is required"})
return
}
if newConfig.OutdoorDeviceModel == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "OutdoorDeviceModel is required"})
return
}
if newConfig.RecommendationIntervalMinutes <= 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "RecommendationIntervalMinutes must be greater than 0"})
return
}
// Update the global config
oldInterval := config.RecommendationIntervalMinutes
config = newConfig
// Save to file
if err := saveConfig(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save configuration"})
return
}
// If recommendation interval changed, restart the recommendation worker
if oldInterval != newConfig.RecommendationIntervalMinutes {
restartRecommendationWorker()
}
c.JSON(http.StatusOK, gin.H{"message": "Configuration updated successfully", "config": config})
}