✨ Implement WebSocket API
This commit is contained in:
130
api.go
130
api.go
@ -1,12 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{}
|
||||
|
||||
type WsClient struct {
|
||||
SendUpdates bool
|
||||
}
|
||||
|
||||
var wsClients = make(map[*websocket.Conn]WsClient)
|
||||
|
||||
func initApi() {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
router := gin.Default()
|
||||
@ -26,6 +36,8 @@ func initApi() {
|
||||
router.PUT("/api/routes", handleSetRoute)
|
||||
router.DELETE("/api/routes", handleDeleteRoute)
|
||||
|
||||
router.GET("/ws", handleWs)
|
||||
|
||||
router.Run(fmt.Sprintf("%s:%d", config.Web.Bind, config.Web.Port))
|
||||
}
|
||||
|
||||
@ -108,6 +120,7 @@ func createPort(body CreatePortRequest) (gin.H, gin.H) {
|
||||
portConfig.Output = append(portConfig.Output, newPort)
|
||||
}
|
||||
saveConfig("ports", &portConfig)
|
||||
onPortListChange()
|
||||
return gin.H{"success": true, "UUID": id}, nil
|
||||
}
|
||||
|
||||
@ -139,6 +152,7 @@ func deletePort(id string) gin.H {
|
||||
unregisterPort(port)
|
||||
|
||||
saveConfig("ports", &portConfig)
|
||||
onPortListChange()
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -199,6 +213,7 @@ func setState(id string, body SetPortRequest) (gin.H, gin.H) {
|
||||
}
|
||||
|
||||
saveConfig("ports", &portConfig)
|
||||
onPortChange(port)
|
||||
return gin.H{"success": true, "state": port.State}, nil
|
||||
}
|
||||
|
||||
@ -236,6 +251,7 @@ func createRoute(id string, body CreateRouteRequest) gin.H {
|
||||
|
||||
from.Route = append(from.Route, PortRoute{ToUUID: body.To, Mute: true, Volume: 0, Balance: 0})
|
||||
saveConfig("ports", &portConfig)
|
||||
onPortChange(from)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -285,6 +301,7 @@ func setRoute(fromId string, toId string, body SetRouteRequest) (gin.H, gin.H) {
|
||||
}
|
||||
|
||||
saveConfig("ports", &portConfig)
|
||||
onPortChange(from)
|
||||
return gin.H{"success": true, "state": from.Route[i]}, nil
|
||||
}
|
||||
|
||||
@ -315,8 +332,121 @@ func deleteRoute(fromId string, toId string) gin.H {
|
||||
|
||||
from.Route = append(from.Route[:i], from.Route[i+1:]...)
|
||||
saveConfig("ports", &portConfig)
|
||||
onPortListChange()
|
||||
return nil
|
||||
}
|
||||
|
||||
return gin.H{"success": false, "error": "No such route exists!"}
|
||||
}
|
||||
|
||||
type WebsocketMessage struct {
|
||||
RequestId string `json:"requestId"`
|
||||
Method string `json:"method"`
|
||||
UUID string `json:"UUID"`
|
||||
ToUUID string `json:"toUUID"`
|
||||
PortData CreatePortRequest `json:"portData"`
|
||||
StateData SetPortRequest `json:"stateData"`
|
||||
RouteData CreateRouteRequest `json:"routeData"`
|
||||
RouteStateData SetRouteRequest `json:"routeStateData"`
|
||||
}
|
||||
|
||||
type WebsocketResponse struct {
|
||||
Type string `json:"type"`
|
||||
RequestId string `json:"requestId,omitempty"`
|
||||
RequestMethod string `json:"requestMethod,omitempty"`
|
||||
ResponseData interface{} `json:"responseData"`
|
||||
}
|
||||
|
||||
func wsSendRes(conn *websocket.Conn, res gin.H, err gin.H, request *WebsocketMessage) {
|
||||
if err != nil {
|
||||
data, _ := json.Marshal(WebsocketResponse{
|
||||
Type: "error",
|
||||
RequestId: request.RequestId,
|
||||
RequestMethod: request.Method,
|
||||
ResponseData: err,
|
||||
})
|
||||
conn.WriteMessage(1, data)
|
||||
return
|
||||
}
|
||||
|
||||
response := WebsocketResponse{
|
||||
Type: "response",
|
||||
RequestId: request.RequestId,
|
||||
RequestMethod: request.Method,
|
||||
ResponseData: gin.H{"success": true},
|
||||
}
|
||||
if res != nil {
|
||||
response.ResponseData = res
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(response)
|
||||
conn.WriteMessage(1, data)
|
||||
}
|
||||
|
||||
func handleWs(c *gin.Context) {
|
||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
fmt.Println("WARN! Handling websocket connection failed!")
|
||||
c.JSON(500, gin.H{"success": false, "error": "Handling websocket connection failed!"})
|
||||
}
|
||||
|
||||
wsClients[conn] = WsClient{SendUpdates: false}
|
||||
|
||||
for {
|
||||
var content WebsocketMessage
|
||||
jsonErr := conn.ReadJSON(&content)
|
||||
if jsonErr != nil {
|
||||
delete(wsClients, conn)
|
||||
conn.Close()
|
||||
break
|
||||
}
|
||||
var res, err gin.H = nil, nil
|
||||
switch content.Method {
|
||||
case "listPorts":
|
||||
res = gin.H{"inputs": portConfig.Input, "outputs": portConfig.Output}
|
||||
case "createPort":
|
||||
res, err = createPort(content.PortData)
|
||||
case "setPortState":
|
||||
res, err = setState(content.UUID, content.StateData)
|
||||
case "deletePort":
|
||||
err = deletePort(content.UUID)
|
||||
case "createRoute":
|
||||
err = createRoute(content.UUID, content.RouteData)
|
||||
case "setRouteState":
|
||||
res, err = setRoute(content.UUID, content.ToUUID, content.RouteStateData)
|
||||
case "deleteRoute":
|
||||
err = deleteRoute(content.UUID, content.ToUUID)
|
||||
case "enableUpdates":
|
||||
if clientOpts, ok := wsClients[conn]; ok {
|
||||
clientOpts.SendUpdates = true
|
||||
wsClients[conn] = clientOpts
|
||||
}
|
||||
default:
|
||||
err = gin.H{"success": false, "error": "Method is not implemented"}
|
||||
}
|
||||
wsSendRes(conn, res, err, &content)
|
||||
}
|
||||
}
|
||||
|
||||
func onPortChange(port *Port) {
|
||||
for conn := range wsClients {
|
||||
if !wsClients[conn].SendUpdates {
|
||||
continue
|
||||
}
|
||||
jsonData, _ := json.Marshal(WebsocketResponse{Type: "portChange", ResponseData: port})
|
||||
conn.WriteMessage(1, jsonData)
|
||||
}
|
||||
}
|
||||
|
||||
func onPortListChange() {
|
||||
for conn := range wsClients {
|
||||
if !wsClients[conn].SendUpdates {
|
||||
continue
|
||||
}
|
||||
jsonData, _ := json.Marshal(WebsocketResponse{
|
||||
Type: "postListChange",
|
||||
ResponseData: gin.H{"inputs": portConfig.Input, "outputs": portConfig.Output},
|
||||
})
|
||||
conn.WriteMessage(1, jsonData)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user