package device import ( "net/http" "strconv" "yovision.local/sense/app/sense/identity" "yovision.local/sense/internal/platform" ) type Module struct{ service *Service } func NewModule(service *Service) *Module { return &Module{service: service} } func (m *Module) Register(app *platform.App) { activeService.Store(m.service) app.Handle("GET /api/v1/devices", identity.Require(identity.PermissionDeviceRead, http.HandlerFunc(m.list))) app.Handle("POST /api/v1/devices", identity.Require(identity.PermissionDeviceWrite, http.HandlerFunc(m.create))) app.Handle("GET /api/v1/devices/{id}", identity.Require(identity.PermissionDeviceRead, http.HandlerFunc(m.get))) app.Handle("PATCH /api/v1/devices/{id}", identity.Require(identity.PermissionDeviceWrite, http.HandlerFunc(m.update))) app.Handle("POST /api/v1/devices/{id}/credentials", identity.Require(identity.PermissionDeviceWrite, http.HandlerFunc(m.credential))) app.Handle("POST /api/v1/devices/{id}/disable", identity.Require(identity.PermissionDeviceWrite, http.HandlerFunc(m.disable))) } func (m *Module) list(w http.ResponseWriter, r *http.Request) { page, _ := strconv.Atoi(r.URL.Query().Get("page")) size, _ := strconv.Atoi(r.URL.Query().Get("page_size")) result, err := m.service.List(r.Context(), ListFilter{Keyword: r.URL.Query().Get("keyword"), Page: page, PageSize: size}) if err != nil { platform.WriteError(w, err) return } platform.WriteJSON(w, http.StatusOK, result) } func (m *Module) get(w http.ResponseWriter, r *http.Request) { item, err := m.service.Get(r.Context(), r.PathValue("id")) if err != nil { writeDeviceError(w, err) return } platform.WriteJSON(w, http.StatusOK, item) } func (m *Module) create(w http.ResponseWriter, r *http.Request) { var req struct { Name string `json:"name"` Location string `json:"location"` Modality string `json:"modality"` Capabilities []string `json:"capabilities"` } if err := platform.DecodeJSON(r, &req); err != nil { platform.WriteError(w, err) return } actor, _ := identity.PrincipalFromContext(r.Context()) item, err := m.service.Create(r.Context(), actor, req.Name, req.Location, req.Modality, req.Capabilities) if err != nil { writeDeviceError(w, err) return } platform.WriteJSON(w, http.StatusCreated, item) } func (m *Module) update(w http.ResponseWriter, r *http.Request) { var req struct { Name string `json:"name"` Location string `json:"location"` Capabilities []string `json:"capabilities"` Version int64 `json:"version"` } if err := platform.DecodeJSON(r, &req); err != nil { platform.WriteError(w, err) return } actor, _ := identity.PrincipalFromContext(r.Context()) item, err := m.service.Update(r.Context(), actor, r.PathValue("id"), req.Name, req.Location, req.Capabilities, req.Version) if err != nil { writeDeviceError(w, err) return } platform.WriteJSON(w, http.StatusOK, item) } func (m *Module) credential(w http.ResponseWriter, r *http.Request) { var req struct { Username string `json:"username"` Password string `json:"password"` ONVIFUsername string `json:"onvif_username"` ONVIFPassword string `json:"onvif_password"` RTSPSameAsONVIF *bool `json:"rtsp_same_as_onvif"` RTSPUsername string `json:"rtsp_username"` RTSPPassword string `json:"rtsp_password"` } if err := platform.DecodeJSON(r, &req); err != nil { platform.WriteError(w, err) return } actor, _ := identity.PrincipalFromContext(r.Context()) if req.ONVIFUsername == "" { req.ONVIFUsername = req.Username } if req.ONVIFPassword == "" { req.ONVIFPassword = req.Password } rtspSame := true if req.RTSPSameAsONVIF != nil { rtspSame = *req.RTSPSameAsONVIF } item, err := m.service.SetCredentials(r.Context(), actor, r.PathValue("id"), req.ONVIFUsername, req.ONVIFPassword, rtspSame, req.RTSPUsername, req.RTSPPassword) if err != nil { writeDeviceError(w, err) return } platform.WriteJSON(w, http.StatusOK, item) } func (m *Module) disable(w http.ResponseWriter, r *http.Request) { var req struct { Version int64 `json:"version"` } if err := platform.DecodeJSON(r, &req); err != nil { platform.WriteError(w, err) return } actor, _ := identity.PrincipalFromContext(r.Context()) item, err := m.service.Disable(r.Context(), actor, r.PathValue("id"), req.Version) if err != nil { writeDeviceError(w, err) return } platform.WriteJSON(w, http.StatusOK, item) } func writeDeviceError(w http.ResponseWriter, err error) { status := http.StatusBadRequest code := "device_invalid" if err == ErrNotFound { status = http.StatusNotFound code = "device_not_found" } if err == ErrConflict { status = http.StatusConflict code = "version_conflict" } platform.WriteError(w, &platform.APIError{Status: status, Code: code, Message: err.Error()}) }