mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
- implement simulator endpoints
- add field for simulation models to simulator models and adapt methods for adding/updating a model - minor renaming of test functions
This commit is contained in:
parent
e820d25aae
commit
86e380c85e
8 changed files with 262 additions and 37 deletions
|
@ -100,6 +100,8 @@ type Simulator struct {
|
||||||
Properties string
|
Properties string
|
||||||
// Raw properties of simulator as JSON string
|
// Raw properties of simulator as JSON string
|
||||||
RawProperties string
|
RawProperties string
|
||||||
|
// SimulationModels in which the simulator is used
|
||||||
|
SimulationModels []SimulationModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visualization data model
|
// Visualization data model
|
||||||
|
|
|
@ -137,7 +137,6 @@ func updateSignal(c *gin.Context) {
|
||||||
"message": "OK.",
|
"message": "OK.",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSignal godoc
|
// getSignal godoc
|
||||||
|
|
|
@ -109,7 +109,7 @@ var msgInSignalC = common.ResponseMsgSignal{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test /models endpoints
|
// Test /models endpoints
|
||||||
func TestSimulationModelEndpoints(t *testing.T) {
|
func TestSignalEndpoints(t *testing.T) {
|
||||||
|
|
||||||
db := common.DummyInitDB()
|
db := common.DummyInitDB()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
|
@ -45,6 +45,13 @@ func (m *SimulationModel) addToSimulation() error {
|
||||||
var simltr simulator.Simulator
|
var simltr simulator.Simulator
|
||||||
err = simltr.ByID(m.SimulatorID)
|
err = simltr.ByID(m.SimulatorID)
|
||||||
err = db.Model(m).Association("Simulator").Append(&simltr).Error
|
err = db.Model(m).Association("Simulator").Append(&simltr).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = db.Model(&simltr).Association("SimulationModels").Append(m).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// associate simulation model with simulation
|
// associate simulation model with simulation
|
||||||
err = db.Model(&sim).Association("SimulationModels").Append(m).Error
|
err = db.Model(&sim).Association("SimulationModels").Append(m).Error
|
||||||
|
@ -58,11 +65,26 @@ func (m *SimulationModel) Update(modifiedSimulationModel SimulationModel) error
|
||||||
if m.SimulatorID != modifiedSimulationModel.SimulatorID {
|
if m.SimulatorID != modifiedSimulationModel.SimulatorID {
|
||||||
// update simulator
|
// update simulator
|
||||||
var s simulator.Simulator
|
var s simulator.Simulator
|
||||||
|
var s_old simulator.Simulator
|
||||||
err := s.ByID(modifiedSimulationModel.SimulatorID)
|
err := s.ByID(modifiedSimulationModel.SimulatorID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = s_old.ByID(m.SimulatorID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = db.Model(m).Association("Simulator").Replace(s).Error
|
err = db.Model(m).Association("Simulator").Replace(s).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// remove simulation model from old simulator
|
||||||
|
err = db.Model(&s_old).Association("SimulationModels").Delete(m).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// add simulation model to new simulator
|
||||||
|
err = db.Model(&s).Association("SimulationModels").Append(m).Error
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package simulator
|
package simulator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
@ -9,17 +11,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterSimulatorEndpoints(r *gin.RouterGroup) {
|
func RegisterSimulatorEndpoints(r *gin.RouterGroup) {
|
||||||
r.GET("", GetSimulators)
|
r.GET("", getSimulators)
|
||||||
r.POST("", AddSimulator)
|
r.POST("", addSimulator)
|
||||||
r.PUT("/:simulatorID", UpdateSimulator)
|
r.PUT("/:simulatorID", updateSimulator)
|
||||||
r.GET("/:simulatorID", GetSimulator)
|
r.GET("/:simulatorID", getSimulator)
|
||||||
r.DELETE("/:simulatorID", DeleteSimulator)
|
r.DELETE("/:simulatorID", deleteSimulator)
|
||||||
r.POST("/:simulatorID/action", SendActionToSimulator)
|
r.GET("/:simulatorID/models", getModelsOfSimulator)
|
||||||
|
r.POST("/:simulatorID/action", sendActionToSimulator)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSimulators godoc
|
// getSimulators godoc
|
||||||
// @Summary Get all simulators
|
// @Summary Get all simulators
|
||||||
// @ID GetSimulators
|
// @ID getSimulators
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {array} common.SimulatorResponse "Simulator parameters requested by user"
|
// @Success 200 {array} common.SimulatorResponse "Simulator parameters requested by user"
|
||||||
|
@ -28,10 +31,17 @@ func RegisterSimulatorEndpoints(r *gin.RouterGroup) {
|
||||||
// @Failure 404 "Not found"
|
// @Failure 404 "Not found"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 "Internal server error"
|
||||||
// @Router /simulators [get]
|
// @Router /simulators [get]
|
||||||
func GetSimulators(c *gin.Context) {
|
func getSimulators(c *gin.Context) {
|
||||||
|
|
||||||
|
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
db := common.GetDB()
|
db := common.GetDB()
|
||||||
var simulators []common.Simulator
|
var simulators []common.Simulator
|
||||||
err := db.Order("ID asc").Find(&simulators).Error
|
err = db.Order("ID asc").Find(&simulators).Error
|
||||||
if common.ProvideErrorResponse(c, err) {
|
if common.ProvideErrorResponse(c, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -41,9 +51,9 @@ func GetSimulators(c *gin.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddSimulator godoc
|
// addSimulator godoc
|
||||||
// @Summary Add a simulator
|
// @Summary Add a simulator
|
||||||
// @ID AddSimulator
|
// @ID addSimulator
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
|
@ -54,15 +64,35 @@ func GetSimulators(c *gin.Context) {
|
||||||
// @Failure 404 "Not found"
|
// @Failure 404 "Not found"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 "Internal server error"
|
||||||
// @Router /simulators [post]
|
// @Router /simulators [post]
|
||||||
func AddSimulator(c *gin.Context) {
|
func addSimulator(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"message": "NOT implemented",
|
err := common.ValidateRole(c, common.ModelSimulator, common.Create)
|
||||||
})
|
if err != nil {
|
||||||
|
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var newSimulator Simulator
|
||||||
|
err = c.BindJSON(&newSimulator)
|
||||||
|
if err != nil {
|
||||||
|
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": errormsg,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = newSimulator.save()
|
||||||
|
if common.ProvideErrorResponse(c, err) == false {
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"message": "OK.",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSimulator godoc
|
// updateSimulator godoc
|
||||||
// @Summary Update a simulator
|
// @Summary Update a simulator
|
||||||
// @ID UpdateSimulator
|
// @ID updateSimulator
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
@ -74,15 +104,49 @@ func AddSimulator(c *gin.Context) {
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID} [put]
|
// @Router /simulators/{simulatorID} [put]
|
||||||
func UpdateSimulator(c *gin.Context) {
|
func updateSimulator(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
err := common.ValidateRole(c, common.ModelSimulator, common.Update)
|
||||||
"message": "NOT implemented",
|
if err != nil {
|
||||||
})
|
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var modifiedSimulator Simulator
|
||||||
|
err = c.BindJSON(&modifiedSimulator)
|
||||||
|
if err != nil {
|
||||||
|
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": errormsg,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
|
||||||
|
if err != nil {
|
||||||
|
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": errormsg,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var s Simulator
|
||||||
|
err = s.ByID(uint(simulatorID))
|
||||||
|
if common.ProvideErrorResponse(c, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.update(modifiedSimulator)
|
||||||
|
if common.ProvideErrorResponse(c, err) == false {
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"message": "OK.",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSimulator godoc
|
// getSimulator godoc
|
||||||
// @Summary Get simulator
|
// @Summary Get simulator
|
||||||
// @ID GetSimulator
|
// @ID getSimulator
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Success 200 {object} common.SimulatorResponse "Simulator requested by user"
|
// @Success 200 {object} common.SimulatorResponse "Simulator requested by user"
|
||||||
|
@ -92,15 +156,38 @@ func UpdateSimulator(c *gin.Context) {
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID} [get]
|
// @Router /simulators/{simulatorID} [get]
|
||||||
func GetSimulator(c *gin.Context) {
|
func getSimulator(c *gin.Context) {
|
||||||
|
|
||||||
|
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
|
||||||
|
if err != nil {
|
||||||
|
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": errormsg,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var s Simulator
|
||||||
|
err = s.ByID(uint(simulatorID))
|
||||||
|
if common.ProvideErrorResponse(c, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer := common.SimulatorSerializer{c, s.Simulator}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "NOT implemented",
|
"simulator": serializer.Response(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSimulator godoc
|
// deleteSimulator godoc
|
||||||
// @Summary Delete a simulator
|
// @Summary Delete a simulator
|
||||||
// @ID DeleteSimulator
|
// @ID deleteSimulator
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 "OK."
|
// @Success 200 "OK."
|
||||||
|
@ -110,15 +197,90 @@ func GetSimulator(c *gin.Context) {
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID} [delete]
|
// @Router /simulators/{simulatorID} [delete]
|
||||||
func DeleteSimulator(c *gin.Context) {
|
func deleteSimulator(c *gin.Context) {
|
||||||
|
|
||||||
|
err := common.ValidateRole(c, common.ModelSimulator, common.Delete)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
|
||||||
|
if err != nil {
|
||||||
|
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": errormsg,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var s Simulator
|
||||||
|
err = s.ByID(uint(simulatorID))
|
||||||
|
if common.ProvideErrorResponse(c, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.delete()
|
||||||
|
if common.ProvideErrorResponse(c, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "NOT implemented",
|
"message": "OK.",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendActionToSimulator godoc
|
// getModelsOfSimulator godoc
|
||||||
|
// @Summary Get all simulation models in which the simulator is used
|
||||||
|
// @ID getModelsOfSimulator
|
||||||
|
// @Tags simulators
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 "OK."
|
||||||
|
// @Failure 401 "Unauthorized Access"
|
||||||
|
// @Failure 403 "Access forbidden."
|
||||||
|
// @Failure 404 "Not found"
|
||||||
|
// @Failure 500 "Internal server error"
|
||||||
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
|
// @Router /simulators/{simulatorID}/models [get]
|
||||||
|
func getModelsOfSimulator(c *gin.Context) {
|
||||||
|
|
||||||
|
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
|
||||||
|
if err != nil {
|
||||||
|
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": errormsg,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var s Simulator
|
||||||
|
err = s.ByID(uint(simulatorID))
|
||||||
|
if common.ProvideErrorResponse(c, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all associated simulation models
|
||||||
|
allModels, _, err := s.getModels()
|
||||||
|
if common.ProvideErrorResponse(c, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer := common.SimulationModelsSerializer{c, allModels}
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"models": serializer.Response(),
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendActionToSimulator godoc
|
||||||
// @Summary Send an action to simulator
|
// @Summary Send an action to simulator
|
||||||
// @ID SendActionToSimulator
|
// @ID sendActionToSimulator
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param inputAction query string true "Action for simulator"
|
// @Param inputAction query string true "Action for simulator"
|
||||||
|
@ -129,7 +291,7 @@ func DeleteSimulator(c *gin.Context) {
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID}/action [post]
|
// @Router /simulators/{simulatorID}/action [post]
|
||||||
func SendActionToSimulator(c *gin.Context) {
|
func sendActionToSimulator(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "NOT implemented",
|
"message": "NOT implemented",
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,3 +24,43 @@ func (s *Simulator) ByID(id uint) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Simulator) update(modifiedSimulator Simulator) error {
|
||||||
|
|
||||||
|
db := common.GetDB()
|
||||||
|
|
||||||
|
err := db.Model(s).Updates(map[string]interface{}{
|
||||||
|
"UUID": modifiedSimulator.UUID,
|
||||||
|
"Host": modifiedSimulator.Host,
|
||||||
|
"Modeltype": modifiedSimulator.Modeltype,
|
||||||
|
"Uptime": modifiedSimulator.Uptime,
|
||||||
|
"State": modifiedSimulator.State,
|
||||||
|
"StateUpdateAt": modifiedSimulator.StateUpdateAt,
|
||||||
|
"Properties": modifiedSimulator.Properties,
|
||||||
|
"RawProperties": modifiedSimulator.RawProperties,
|
||||||
|
}).Error
|
||||||
|
|
||||||
|
return err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Simulator) delete() error {
|
||||||
|
db := common.GetDB()
|
||||||
|
|
||||||
|
no_simulationmodels := db.Model(s).Association("SimulationModel").Count()
|
||||||
|
|
||||||
|
if no_simulationmodels > 0 {
|
||||||
|
return fmt.Errorf("Simulator cannot be deleted as it is still used in SimulationModels (active or dangling)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete Simulator from DB (does NOT remain as dangling)
|
||||||
|
err := db.Delete(s).Error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Simulator) getModels() ([]common.SimulationModel, int, error) {
|
||||||
|
db := common.GetDB()
|
||||||
|
var models []common.SimulationModel
|
||||||
|
err := db.Order("ID asc").Model(s).Related(&models, "SimulationModels").Error
|
||||||
|
return models, len(models), err
|
||||||
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ var msgVisupdated = common.ResponseMsgVisualization{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test /models endpoints
|
// Test /models endpoints
|
||||||
func TestSimulationModelEndpoints(t *testing.T) {
|
func TestVisualizationEndpoints(t *testing.T) {
|
||||||
|
|
||||||
db := common.DummyInitDB()
|
db := common.DummyInitDB()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
|
@ -140,7 +140,7 @@ var msgWdgupdated = common.ResponseMsgWidget{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test /models endpoints
|
// Test /models endpoints
|
||||||
func TestSimulationModelEndpoints(t *testing.T) {
|
func TestWidgetEndpoints(t *testing.T) {
|
||||||
|
|
||||||
db := common.DummyInitDB()
|
db := common.DummyInitDB()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
Loading…
Add table
Reference in a new issue