generated from VLADIMIR/template
up
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"evening_detective_server/internal/modules/cudy"
|
||||
"evening_detective_server/internal/services/wifi_service"
|
||||
)
|
||||
|
||||
func collectCudy() {
|
||||
path := os.Getenv("CUDY_SNAPSHOT_FILE")
|
||||
if path == "" {
|
||||
log.Fatal("CUDY_SNAPSHOT_FILE is required")
|
||||
}
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
snapshot := cudy.Snapshot{}
|
||||
var reader cudy.Reader
|
||||
passwordFile := os.Getenv("CUDY_PASSWORD_FILE")
|
||||
if passwordFile != "" {
|
||||
password, err := os.ReadFile(passwordFile)
|
||||
if err != nil {
|
||||
log.Fatal("cannot read Cudy credential file")
|
||||
}
|
||||
base := os.Getenv("CUDY_URL")
|
||||
if base == "" {
|
||||
base = "http://192.168.10.1"
|
||||
}
|
||||
reader, err = cudy.NewReader(base, strings.TrimRight(string(password), "\r\n"))
|
||||
if err != nil {
|
||||
log.Fatal("invalid Cudy configuration")
|
||||
}
|
||||
snapshot, _ = wifi_service.New(path).Get(ctx)
|
||||
snapshot.Enabled = true
|
||||
}
|
||||
timer := time.NewTicker(10 * time.Second)
|
||||
defer timer.Stop()
|
||||
for {
|
||||
if reader != nil {
|
||||
clients, err := reader.Read(ctx)
|
||||
snapshot.HasError = err != nil
|
||||
if err == nil {
|
||||
snapshot.Clients = clients
|
||||
snapshot.CollectedAt = time.Now().UTC()
|
||||
}
|
||||
}
|
||||
if err := writeCudySnapshot(path, snapshot); err != nil {
|
||||
log.Print("cannot publish Cudy snapshot")
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-timer.C:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writeCudySnapshot(path string, snapshot cudy.Snapshot) error {
|
||||
data, err := json.Marshal(snapshot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.CreateTemp(filepath.Dir(path), ".cudy-")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name := file.Name()
|
||||
defer os.Remove(name)
|
||||
if err = file.Chmod(0644); err == nil {
|
||||
_, err = file.Write(data)
|
||||
}
|
||||
closeErr := file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if closeErr != nil {
|
||||
return closeErr
|
||||
}
|
||||
return os.Rename(name, path)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"evening_detective_server/internal/modules/cudy"
|
||||
)
|
||||
|
||||
func TestAtomicCudySnapshot(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "state.json")
|
||||
for _, failed := range []bool{false, true} {
|
||||
snapshot := cudy.Snapshot{Enabled: true, CollectedAt: time.Unix(123, 0), HasError: failed, Clients: []cudy.Client{{MAC: "AA:BB:CC:DD:EE:01"}}}
|
||||
if err := writeCudySnapshot(path, snapshot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var result cudy.Snapshot
|
||||
if json.Unmarshal(data, &result) != nil || result.HasError != failed || len(result.Clients) != 1 {
|
||||
t.Fatal("snapshot corrupted")
|
||||
}
|
||||
}
|
||||
files, err := os.ReadDir(dir)
|
||||
if err != nil || len(files) != 1 {
|
||||
t.Fatal("temporary snapshots left behind")
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,7 @@ import (
|
||||
"evening_detective_server/internal/services/ticket_service"
|
||||
"evening_detective_server/internal/services/ui_service"
|
||||
"evening_detective_server/internal/services/users_service"
|
||||
"evening_detective_server/internal/services/wifi_service"
|
||||
proto "evening_detective_server/proto"
|
||||
"fmt"
|
||||
"log"
|
||||
@@ -89,6 +90,10 @@ const grpcMsgLimit = 257 << 20
|
||||
|
||||
func main() {
|
||||
_ = godotenv.Load()
|
||||
if len(os.Args) == 2 && os.Args[1] == "--collect-cudy" {
|
||||
collectCudy()
|
||||
return
|
||||
}
|
||||
mode := "prod"
|
||||
if os.Getenv("APP_MODE") == "venue" {
|
||||
mode = "venue"
|
||||
@@ -292,6 +297,7 @@ func main() {
|
||||
gameResultsService,
|
||||
gameResultsApplyService,
|
||||
devicePresenceService,
|
||||
wifi_service.New(os.Getenv("CUDY_SNAPSHOT_FILE")),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -5056,6 +5056,10 @@
|
||||
"serverTime": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"wifi": {
|
||||
"$ref": "#/definitions/evening_detective_serverVenueWiFi",
|
||||
"description": "Entire venue, independent of the game filter."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -6346,6 +6350,50 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"evening_detective_serverVenueWiFi": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"collectedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"stale": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"hasError": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"clients": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/evening_detective_serverWiFiClient"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"evening_detective_serverWiFiClient": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"IP": {
|
||||
"type": "string"
|
||||
},
|
||||
"MAC": {
|
||||
"type": "string"
|
||||
},
|
||||
"band": {
|
||||
"type": "string"
|
||||
},
|
||||
"signal": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "dBm; absent when the router does not report it."
|
||||
}
|
||||
}
|
||||
},
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
Reference in New Issue
Block a user