Add device model status API and rebuild agent binary
This commit is contained in:
parent
cf4493507c
commit
540a495d7b
20
agent/internal/httpapi/models_status.go
Normal file
20
agent/internal/httpapi/models_status.go
Normal file
@ -0,0 +1,20 @@
|
||||
package httpapi
|
||||
|
||||
import "net/http"
|
||||
|
||||
func (s *Server) handleModelsStatus(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
errorJSON(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||
return
|
||||
}
|
||||
if !s.authorize(r, false) {
|
||||
errorJSON(w, http.StatusUnauthorized, "unauthorized")
|
||||
return
|
||||
}
|
||||
items, err := s.store.ListInstalledModels()
|
||||
if err != nil {
|
||||
errorJSON(w, http.StatusInternalServerError, "internal error: "+err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{"models": items})
|
||||
}
|
||||
41
agent/internal/httpapi/models_status_test.go
Normal file
41
agent/internal/httpapi/models_status_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"rk3588sys/agent/internal/modelstore"
|
||||
)
|
||||
|
||||
func TestHandleModelsStatusReturnsInstalledModels(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
store := modelstore.New(dir, 8)
|
||||
itemDir := store.FilesDir()
|
||||
if err := os.MkdirAll(itemDir, 0o755); err != nil {
|
||||
t.Fatalf("MkdirAll: %v", err)
|
||||
}
|
||||
modelPath := filepath.Join(itemDir, "face_det_scrfd_500m_640_rk3588__abc.rknn")
|
||||
if err := os.WriteFile(modelPath, []byte("abc"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(store.ManifestPath(), []byte(`{"items":[{"name":"face_det_scrfd_500m_640_rk3588","sha256":"abc","path":"`+filepath.ToSlash(modelPath)+`","size":3,"mtime_ms":1}]}`), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile manifest: %v", err)
|
||||
}
|
||||
|
||||
srv := &Server{store: store}
|
||||
req := httptest.NewRequest(http.MethodGet, "/v1/models/status", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
srv.handleModelsStatus(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", rr.Code, rr.Body.String())
|
||||
}
|
||||
if !strings.Contains(rr.Body.String(), "face_det_scrfd_500m_640_rk3588") {
|
||||
t.Fatalf("expected response to include model name, got %s", rr.Body.String())
|
||||
}
|
||||
}
|
||||
@ -127,6 +127,7 @@ func New(agentCfg config.AgentConfig, baseDir string, ms *mediaserver.Client, st
|
||||
mux.HandleFunc("/v1/face-gallery", s.handleFaceGallery)
|
||||
mux.HandleFunc("/v1/face-gallery/reload", s.handleFaceGalleryReload)
|
||||
mux.HandleFunc("/v1/models", s.handleModelsList)
|
||||
mux.HandleFunc("/v1/models/status", s.handleModelsStatus)
|
||||
mux.HandleFunc("/v1/models/", s.handleModelUpload)
|
||||
mux.HandleFunc("/v1/media-server/reload", s.handleMediaReload)
|
||||
mux.HandleFunc("/v1/media-server/rollback", s.handleMediaRollback)
|
||||
|
||||
@ -26,6 +26,15 @@ type Manifest struct {
|
||||
Items []Item `json:"items"`
|
||||
}
|
||||
|
||||
type InstalledModel struct {
|
||||
Name string `json:"name"`
|
||||
FileName string `json:"file_name"`
|
||||
Sha256 string `json:"sha256"`
|
||||
Path string `json:"path"`
|
||||
Size int64 `json:"size"`
|
||||
MtimeMS int64 `json:"mtime_ms"`
|
||||
}
|
||||
|
||||
type Store struct {
|
||||
ModelsDir string
|
||||
MaxUploadBytes int64
|
||||
@ -136,6 +145,26 @@ func (s *Store) List() (Manifest, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListInstalledModels() ([]InstalledModel, error) {
|
||||
manifest, err := s.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items := make([]InstalledModel, 0, len(manifest.Items))
|
||||
for _, item := range manifest.Items {
|
||||
fileName := filepath.Base(filepath.FromSlash(item.Path))
|
||||
items = append(items, InstalledModel{
|
||||
Name: item.Name,
|
||||
FileName: fileName,
|
||||
Sha256: item.Sha256,
|
||||
Path: item.Path,
|
||||
Size: item.Size,
|
||||
MtimeMS: item.MtimeMS,
|
||||
})
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (s *Store) upsertManifest(item Item) error {
|
||||
m, err := s.List()
|
||||
if err != nil {
|
||||
|
||||
30
agent/internal/modelstore/modelstore_test.go
Normal file
30
agent/internal/modelstore/modelstore_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package modelstore
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestListInstalledModelsUsesManifestEntries(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
store := New(dir, 8)
|
||||
if err := os.MkdirAll(store.FilesDir(), 0o755); err != nil {
|
||||
t.Fatalf("MkdirAll: %v", err)
|
||||
}
|
||||
modelPath := filepath.Join(store.FilesDir(), "face_det_scrfd_500m_640_rk3588__abc.rknn")
|
||||
if err := os.WriteFile(modelPath, []byte("abc"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(store.ManifestPath(), []byte(`{"items":[{"name":"face_det_scrfd_500m_640_rk3588","sha256":"abc","path":"`+filepath.ToSlash(modelPath)+`","size":3,"mtime_ms":1}]}`), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile manifest: %v", err)
|
||||
}
|
||||
|
||||
items, err := store.ListInstalledModels()
|
||||
if err != nil {
|
||||
t.Fatalf("ListInstalledModels: %v", err)
|
||||
}
|
||||
if len(items) != 1 || items[0].FileName == "" {
|
||||
t.Fatalf("unexpected installed models: %#v", items)
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user