package realtime import ( "encoding/json" "net/http" "strings" ) func NewOpenAPIHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { writeError(w, http.StatusMethodNotAllowed, "method not allowed") return } if strings.Trim(r.URL.Path, "/") != "openapi.json" { writeError(w, http.StatusNotFound, "route not found") return } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(realtimeOpenAPISpec()) }) } func NewSwaggerUIHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { writeError(w, http.StatusMethodNotAllowed, "method not allowed") return } w.Header().Set("Content-Type", "text/html; charset=utf-8") _, _ = w.Write([]byte(swaggerHTML)) }) } func realtimeOpenAPISpec() map[string]any { return map[string]any{ "openapi": "3.0.3", "info": map[string]any{ "title": "Lingniu Vehicle Realtime API", "version": "1.0.0", "description": "MySQL realtime query APIs for vehicle_realtime_snapshot and vehicle_realtime_location.", }, "paths": map[string]any{ "/api/realtime/snapshots": map[string]any{ "get": map[string]any{ "summary": "查询车辆实时快照", "description": "从 vehicle_realtime_snapshot 查询各协议最新在线快照,支持协议、VIN、车牌过滤和分页。", "tags": []string{"Realtime Snapshot API"}, "x-table": "vehicle_realtime_snapshot", "parameters": commonRealtimeParameters(), "responses": map[string]any{ "200": map[string]any{ "description": "Snapshot page", "content": map[string]any{ "application/json": map[string]any{ "schema": map[string]any{"$ref": "#/components/schemas/SnapshotPage"}, }, }, }, }, }, }, "/api/realtime/locations": map[string]any{ "get": map[string]any{ "summary": "查询车辆实时位置", "description": "从 vehicle_realtime_location 查询各协议最新位置,支持协议、VIN、车牌过滤和分页。", "tags": []string{"Realtime Location API"}, "x-table": "vehicle_realtime_location", "parameters": commonRealtimeParameters(), "responses": map[string]any{ "200": map[string]any{ "description": "Location page", "content": map[string]any{ "application/json": map[string]any{ "schema": map[string]any{"$ref": "#/components/schemas/LocationPage"}, }, }, }, }, }, }, }, "components": map[string]any{ "schemas": map[string]any{ "SnapshotPage": pageSchema("#/components/schemas/SnapshotRow"), "LocationPage": pageSchema("#/components/schemas/LocationRow"), "SnapshotRow": map[string]any{ "type": "object", "properties": map[string]any{ "protocol": stringSchema("GB32960"), "vin": stringSchema("LB9A32A21R0LS1707"), "plate": stringSchema("浙A12345"), "event_time": stringSchema("2026-07-02 16:01:02.123"), "received_at": stringSchema("2026-07-02 16:01:03.456"), "event_id": stringSchema("event id"), "created_at": stringSchema("2026-07-02 16:01:03"), "updated_at": stringSchema("2026-07-02 16:01:04"), }, }, "LocationRow": map[string]any{ "type": "object", "properties": map[string]any{ "protocol": stringSchema("JT808"), "vin": stringSchema("LKLG7C4E3NA774736"), "plate": stringSchema("粤B98765"), "event_time": stringSchema("2026-07-02 16:11:02.000"), "latitude": numberSchema(30.123456), "longitude": numberSchema(120.654321), "speed_kmh": numberSchema(54.3), "total_mileage_km": numberSchema(48798.9), "soc_percent": numberSchema(81.5), "altitude_m": numberSchema(19.0), "direction_deg": numberSchema(88.0), "alarm_flag": integerSchema(0), "status_flag": integerSchema(3), "received_at": stringSchema("2026-07-02 16:11:03.000"), "event_id": stringSchema("event id"), "created_at": stringSchema("2026-07-02 16:11:03"), "updated_at": stringSchema("2026-07-02 16:11:04"), }, }, }, }, } } func commonRealtimeParameters() []map[string]any { return []map[string]any{ {"name": "protocol", "in": "query", "schema": map[string]any{"type": "string", "enum": []string{"GB32960", "JT808", "YUTONG_MQTT"}}, "required": false}, {"name": "vin", "in": "query", "schema": map[string]any{"type": "string"}, "required": false}, {"name": "plate", "in": "query", "schema": map[string]any{"type": "string"}, "required": false}, {"name": "limit", "in": "query", "schema": map[string]any{"type": "integer", "minimum": 1, "maximum": 1000, "default": 50}, "required": false}, {"name": "offset", "in": "query", "schema": map[string]any{"type": "integer", "minimum": 0, "maximum": 1000000, "default": 0}, "required": false}, } } func pageSchema(itemRef string) map[string]any { return map[string]any{ "type": "object", "properties": map[string]any{ "items": map[string]any{"type": "array", "items": map[string]any{"$ref": itemRef}}, "total": integerSchema(1), "limit": integerSchema(50), "offset": integerSchema(0), }, } } func stringSchema(example string) map[string]any { return map[string]any{"type": "string", "example": example} } func numberSchema(example float64) map[string]any { return map[string]any{"type": "number", "example": example} } func integerSchema(example int64) map[string]any { return map[string]any{"type": "integer", "example": example} } const swaggerHTML = ` Lingniu Vehicle Realtime API
`