SSE impl done

This commit is contained in:
lin committed 2026-10-06 15:49:19 +02:00
1 parent 88b5ff98cd
commit cad4ae65f7
4 files changed
+96 -3

No files matched your search

-2
View File
@@ -24,5 +24,3 @@ go.work.sum
# env file
.env
!lhm/*
+8
View File
@@ -5,8 +5,16 @@ import (
"rpi5-health/internal/http_internal"
)
/* TODO:
* 1. Storage & Disk I/O: Disk capacity | Disk I/O rates | IOWAIT metrics
* 2. Network traffic: Bandwidth usage | Total network usage | Active connections
* 3. Process monitoring: Top consumers | Zombie processes */
func main() {
srv := http_internal.NewAppServer()
srv.RegisterRoute("/api/events", http_internal.SSEHandler)
go srv.Start()
cli.Listen()
+21 -1
View File
@@ -1,12 +1,28 @@
package http_internal
import "net/http"
import (
"net/http"
loadaverage "rpi5-health/internal/load_average"
"rpi5-health/internal/memory"
"rpi5-health/internal/processor"
"rpi5-health/internal/temperature"
"rpi5-health/internal/uptime"
)
type AppServer struct {
srv *http.Server
mux *http.ServeMux
}
// To be sent to the client
type ServerStatistics struct {
LoadAvgInfo loadaverage.LoadAverageInformation `json:"load_average"`
MemoryInfo memory.MemoryInformation `json:"memory_info"`
ProcessorInfo processor.ProcessorInformation `json:"processor_info"`
TemperatureInfo temperature.TemperatureInformation `json:"temperature_info"`
UptimeInfo uptime.UptimeInformation `json:"uptime_info"`
}
func NewAppServer() *AppServer {
mux := http.NewServeMux()
@@ -28,3 +44,7 @@ func NewAppServer() *AppServer {
func (srv *AppServer) Start() {
srv.srv.ListenAndServe()
}
func (srv *AppServer) RegisterRoute(endpoint string, handler http.HandlerFunc) {
srv.mux.HandleFunc(endpoint, handler)
}
+67
View File
@@ -0,0 +1,67 @@
package http_internal
import (
"encoding/json"
"fmt"
"log"
"net/http"
loadaverage "rpi5-health/internal/load_average"
"rpi5-health/internal/memory"
"rpi5-health/internal/processor"
"rpi5-health/internal/temperature"
"rpi5-health/internal/uptime"
"time"
)
func SSEHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
// For CORS requests
w.Header().Set("Access-Control-Allow-Origin", "*")
clientGone := r.Context().Done() // Channel to signal client disconnection
rc := http.NewResponseController(w)
t := time.NewTicker(time.Second * 5)
defer t.Stop()
for {
select {
case <-clientGone:
log.Println("Client disconnected")
return
case <-t.C:
resp := buildDashboardResponse()
_, err := fmt.Fprintf(w, "data: %s\n\n", resp)
if err != nil {
return
}
err = rc.Flush()
if err != nil {
return
}
}
}
}
func buildDashboardResponse() []byte {
// TODO: proper error handling
loadavg, _ := loadaverage.GetLoadAverage()
memoryInfo, _ := memory.GetRamInformation()
processorInfo := processor.GetCPUInformation()
temperatureInfo, _ := temperature.GetTemperatureInformation()
uptimeInfo, _ := uptime.GetUptimeInformation()
stats := ServerStatistics{
LoadAvgInfo: loadavg,
MemoryInfo: memoryInfo,
ProcessorInfo: processorInfo,
TemperatureInfo: temperatureInfo,
UptimeInfo: uptimeInfo,
}
payload, _ := json.Marshal(stats)
return payload
}