package robot import ( "jannex/robot-control-manager/modules/cache" "jannex/robot-control-manager/modules/database" "jannex/robot-control-manager/modules/logger" "jannex/robot-control-manager/modules/robot" "jannex/robot-control-manager/modules/structs" "jannex/robot-control-manager/modules/utils" "time" "git.ex.umbach.dev/Alex/roese-utils/rspagination" "git.ex.umbach.dev/Alex/roese-utils/rsutils" "github.com/gofiber/fiber/v2" "github.com/google/uuid" ) func FirstRequest(c *fiber.Ctx) error { // swagger:operation POST /robot robot robotFirstRequest // --- // summary: First request from robot. // description: | // This is the first request from the robot. It will be used to identify the robot. // consumes: // - application/json // produces: // - application/json // parameters: // - in: body // name: body // description: First request body. // required: true // schema: // "$ref": "#/definitions/FirstRequestBody" // responses: // "200": // description: Robot identified // schema: // "$ref": "#/definitions/StatusResponse" // "400": // description: Invalid request body // "403": // description: Permit join is enabled var body structs.FirstRequestBody if err := rsutils.BodyParserHelper(c, &body); err != nil { return c.SendStatus(fiber.StatusBadRequest) } var foundRobot structs.Robot database.DB.First(&foundRobot, "id = ?", body.Id) if !cache.IsPermitJoinEnabled() && foundRobot.Id == "" { logger.AddSystemLog("Unauthorized robot tried to connect with id %v and type %v", body.Id, utils.GetRobotTypeString(body.Type)) return c.SendStatus(fiber.StatusForbidden) } if foundRobot.Id == "" { now := time.Now() newUnauthorizedRobot := structs.UnauthorizedRobot{ Id: body.Id, Type: body.Type, Address: c.IP(), FirmwareVersion: body.FirmwareVersion, ConnectedAt: now, CreatedAt: now, } cache.AddUnauthorizedRobot(&newUnauthorizedRobot) totalPages := cache.GetAllUnauthorizedRobots(rspagination.PageQuery{Page: 1}).TotalPages robot.BroadcastSSEMessage(structs.SSEMessage{ Cmd: utils.SSESentCmdAddUnauthorizedRobot, Body: struct { UnauthorizedRobot *structs.UnauthorizedRobot TotalPages int }{ UnauthorizedRobot: &newUnauthorizedRobot, TotalPages: totalPages, }, }) logger.AddSystemLog("Unauthorized robot connected with id %v and type %v", body.Id, utils.GetRobotTypeString(body.Type)) } else { newRobot := structs.Robot{ Id: body.Id, Type: body.Type, Name: foundRobot.Name, Status: utils.RobotStatusIdle, Address: c.IP(), CurrentJobId: "", FirmwareVersion: body.FirmwareVersion, ConnectedAt: time.Now(), CreatedAt: foundRobot.CreatedAt, } cache.AddRobot(&newRobot) database.DB.Model(&structs.Robot{}). Where("id = ?", newRobot.Id). Updates(structs.Robot{ Status: newRobot.Status, Type: newRobot.Type, Address: newRobot.Address, FirmwareVersion: newRobot.FirmwareVersion, }) addRobotSSEMessage(&newRobot) logger.AddSystemLog("Robot connected with id %v and type %v", body.Id, utils.GetRobotTypeString(body.Type)) } return c.JSON(structs.StatusResponse{Status: "ok"}) } func addRobotSSEMessage(newRobot *structs.Robot) { totalPages := cache.GetAllRobots(rspagination.PageQuery{Page: 1}).TotalPages robot.BroadcastSSEMessage(structs.SSEMessage{ Cmd: utils.SSESentCmdAddRobot, Body: struct { Robot *structs.Robot TotalPages int UnauthorizedRobotsTotalPages int }{ Robot: newRobot, TotalPages: totalPages, UnauthorizedRobotsTotalPages: cache.GetAllUnauthorizedRobots(rspagination.PageQuery{Page: 1}).TotalPages, }, }) } func AuthorizeRobot(c *fiber.Ctx) error { // swagger:operation POST /robot/authorize/{robotId} robot robotAuthorize // --- // summary: Authorize robot. // consumes: // - application/json // produces: // - application/json // parameters: // - in: params // name: robotId // description: Robot id. // required: true // schema: // type: string // responses: // "200": // description: Robot authorized // "400": // description: Invalid robot id // "422": // description: Robot not found var params structs.RobotIdParams if err := rsutils.ParamsParserHelper(c, ¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !cache.IsUnauthorizedRobotInList(params.RobotId) { logger.AddSystemLog("Unauthorized robot with id %v not found", params.RobotId) return c.SendStatus(fiber.StatusUnprocessableEntity) } unauthorizedRobot := cache.GetUnauthorizedRobotById(params.RobotId) if unauthorizedRobot.Id == "" { return c.SendStatus(fiber.StatusUnprocessableEntity) } newRobot := structs.Robot{ Id: params.RobotId, Type: unauthorizedRobot.Type, Name: uuid.New().String(), Address: unauthorizedRobot.Address, Status: utils.RobotStatusIdle, FirmwareVersion: unauthorizedRobot.FirmwareVersion, ConnectedAt: unauthorizedRobot.ConnectedAt, CreatedAt: unauthorizedRobot.CreatedAt, } cache.AddRobot(&newRobot) database.DB.Create(&newRobot) cache.RemoveUnauthorizedRobotById(params.RobotId) addRobotSSEMessage(&newRobot) logger.AddSystemLog("Robot authorized with id %v and type %v", params.RobotId, utils.GetRobotTypeString(unauthorizedRobot.Type)) return c.SendStatus(fiber.StatusOK) } func DeleteRobot(c *fiber.Ctx) error { // swagger:operation DELETE /robot/{robotId} robot robotDelete // --- // summary: Delete robot. // consumes: // - application/json // produces: // - application/json // parameters: // - in: path // name: robotId // description: Robot id. // required: true // schema: // type: string // responses: // "200": // description: Robot deleted // "400": // description: Invalid robot id var params structs.RobotIdParams if err := rsutils.ParamsParserHelper(c, ¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } database.DB.Delete(&structs.Robot{}, "id = ?", params.RobotId) cache.RemoveRobotById(params.RobotId) robot.BroadcastSSEMessage(structs.SSEMessage{ Cmd: utils.SSESentCmdRemoveRobot, Body: struct { RobotId string TotalPages int }{ RobotId: params.RobotId, TotalPages: cache.GetAllRobots(rspagination.PageQuery{Page: 1}).TotalPages, }, }) logger.AddSystemLog("Robot deleted with id %v", params.RobotId) return c.SendStatus(fiber.StatusOK) } func DenyUnauthorizedRobot(c *fiber.Ctx) error { // swagger:operation DELETE /robot/deny/{robotId} robot robotDenyUnauthorizedRobot // --- // summary: Deny unauthorized robot. // consumes: // - application/json // produces: // - application/json // parameters: // - in: path // name: robotId // description: Robot id. // required: true // schema: // type: string // responses: // "200": // description: Robot denied // "400": // description: Invalid robot id var params structs.RobotIdParams if err := rsutils.ParamsParserHelper(c, ¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } cache.RemoveUnauthorizedRobotById(params.RobotId) robot.BroadcastSSEMessage(structs.SSEMessage{ Cmd: utils.SSESentCmdRemoveUnauthorizedRobot, Body: struct { UnauthorizedRobotId string TotalPages int }{ UnauthorizedRobotId: params.RobotId, TotalPages: cache.GetAllUnauthorizedRobots(rspagination.PageQuery{Page: 1}).TotalPages, }, }) logger.AddSystemLog("Unauthorized robot denied with id %v", params.RobotId) return c.SendStatus(fiber.StatusOK) } func UpdateRobot(c *fiber.Ctx) error { // swagger:operation PATCH /robot robot robotUpdate // --- // summary: Update robot. // consumes: // - application/json // produces: // - application/json // parameters: // - in: body // name: body // description: Update robot body. // required: true // schema: // "$ref": "#/definitions/Robot" // responses: // "200": // description: Robot updated // "400": // description: Invalid request body // "422": // description: Robot not found var body structs.UpdateRobotBody if err := rsutils.BodyParserHelper(c, &body); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !cache.IsRobotInList(body.RobotId) { logger.AddSystemLog("Robot with id %v not found", body.RobotId) return c.SendStatus(fiber.StatusUnprocessableEntity) } foundRobot := cache.GetRobotById(body.RobotId) if foundRobot == nil || cache.IsRobotNameInList(body.Name) { return c.SendStatus(fiber.StatusUnprocessableEntity) } foundRobot.Name = body.Name database.DB.Model(&structs.Robot{}). Where("id = ?", foundRobot.Id). Update("name", foundRobot.Name) robot.BroadcastSSEMessage(structs.SSEMessage{ Cmd: utils.SSESentCmdRobotUpdated, Body: body, }) logger.AddSystemLog("Robot with id %v name changed to %v", body.RobotId, body.Name) return c.SendStatus(fiber.StatusOK) }