|
@@ -5,7 +5,6 @@ import (
|
|
|
"fmt"
|
|
"fmt"
|
|
|
"io"
|
|
"io"
|
|
|
"net/http"
|
|
"net/http"
|
|
|
- "sort"
|
|
|
|
|
"strconv"
|
|
"strconv"
|
|
|
"strings"
|
|
"strings"
|
|
|
"sync"
|
|
"sync"
|
|
@@ -17,11 +16,6 @@ import (
|
|
|
"ai-status-light/internal/web"
|
|
"ai-status-light/internal/web"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-type ClientStatus struct {
|
|
|
|
|
- Code string `json:"code"`
|
|
|
|
|
- Timestamp string `json:"timestamp"`
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
type EventRequest struct {
|
|
type EventRequest struct {
|
|
|
Code string `json:"code"`
|
|
Code string `json:"code"`
|
|
|
Timestamp string `json:"timestamp,omitempty"`
|
|
Timestamp string `json:"timestamp,omitempty"`
|
|
@@ -38,8 +32,6 @@ type Server struct {
|
|
|
server *http.Server
|
|
server *http.Server
|
|
|
sseClients map[*SSEClient]bool
|
|
sseClients map[*SSEClient]bool
|
|
|
sseMu sync.Mutex
|
|
sseMu sync.Mutex
|
|
|
- statusMap map[int]*ClientStatus
|
|
|
|
|
- statusMu sync.RWMutex
|
|
|
|
|
certFile string
|
|
certFile string
|
|
|
keyFile string
|
|
keyFile string
|
|
|
mqttClient *mqttcli.Client
|
|
mqttClient *mqttcli.Client
|
|
@@ -56,11 +48,9 @@ func New(db *database.DB, addr string) *Server {
|
|
|
s := &Server{
|
|
s := &Server{
|
|
|
db: db,
|
|
db: db,
|
|
|
sseClients: make(map[*SSEClient]bool),
|
|
sseClients: make(map[*SSEClient]bool),
|
|
|
- statusMap: make(map[int]*ClientStatus),
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
mux := http.NewServeMux()
|
|
|
- mux.HandleFunc("/api/clients", s.handleClients)
|
|
|
|
|
mux.HandleFunc("/api/event", s.handleEvent)
|
|
mux.HandleFunc("/api/event", s.handleEvent)
|
|
|
mux.HandleFunc("/api/events", s.handleSSE)
|
|
mux.HandleFunc("/api/events", s.handleSSE)
|
|
|
mux.HandleFunc("/api/mqtt", s.handleMQTT)
|
|
mux.HandleFunc("/api/mqtt", s.handleMQTT)
|
|
@@ -224,15 +214,6 @@ func (s *Server) handleSSE(w http.ResponseWriter, r *http.Request) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) broadcastSSE(code string) {
|
|
func (s *Server) broadcastSSE(code string) {
|
|
|
- ts := time.Now().Format(time.RFC3339)
|
|
|
|
|
-
|
|
|
|
|
- s.statusMu.Lock()
|
|
|
|
|
- s.statusMap[0] = &ClientStatus{
|
|
|
|
|
- Code: code,
|
|
|
|
|
- Timestamp: ts,
|
|
|
|
|
- }
|
|
|
|
|
- s.statusMu.Unlock()
|
|
|
|
|
-
|
|
|
|
|
s.sseMu.Lock()
|
|
s.sseMu.Lock()
|
|
|
defer s.sseMu.Unlock()
|
|
defer s.sseMu.Unlock()
|
|
|
|
|
|
|
@@ -242,7 +223,7 @@ func (s *Server) broadcastSSE(code string) {
|
|
|
|
|
|
|
|
payload := map[string]interface{}{
|
|
payload := map[string]interface{}{
|
|
|
"code": code,
|
|
"code": code,
|
|
|
- "timestamp": ts,
|
|
|
|
|
|
|
+ "timestamp": time.Now().Format(time.RFC3339),
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
data, err := json.Marshal(payload)
|
|
data, err := json.Marshal(payload)
|
|
@@ -279,26 +260,6 @@ func (c *SSEClient) Close() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (s *Server) handleClients(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
- if r.Method != http.MethodGet {
|
|
|
|
|
- writeJSON(w, http.StatusMethodNotAllowed, Response{Code: -1, Message: "方法不允许"})
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- s.statusMu.RLock()
|
|
|
|
|
- result := make([]*ClientStatus, 0, len(s.statusMap))
|
|
|
|
|
- for _, cs := range s.statusMap {
|
|
|
|
|
- result = append(result, cs)
|
|
|
|
|
- }
|
|
|
|
|
- s.statusMu.RUnlock()
|
|
|
|
|
-
|
|
|
|
|
- sort.Slice(result, func(i, j int) bool {
|
|
|
|
|
- return result[i].Code < result[j].Code
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- writeJSON(w, http.StatusOK, Response{Code: 0, Message: "success", Data: result})
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
func (s *Server) handleMQTT(w http.ResponseWriter, r *http.Request) {
|
|
func (s *Server) handleMQTT(w http.ResponseWriter, r *http.Request) {
|
|
|
logger.Debug("HTTP %s %s", r.Method, r.URL.Path)
|
|
logger.Debug("HTTP %s %s", r.Method, r.URL.Path)
|
|
|
switch r.Method {
|
|
switch r.Method {
|