Expose business config metadata in agent

This commit is contained in:
tian 2026-04-23 12:35:33 +08:00
parent ac930e90e1
commit 45fadc6699
8 changed files with 98 additions and 74 deletions

View File

@ -51,6 +51,7 @@ type discoverReply struct {
GitSHA string `json:"git_sha"`
ConfigID string `json:"config_id,omitempty"`
ConfigVersion string `json:"config_version,omitempty"`
BusinessName string `json:"business_name,omitempty"`
Template string `json:"template,omitempty"`
Profile string `json:"profile,omitempty"`
Overlays []string `json:"overlays,omitempty"`
@ -123,6 +124,7 @@ func (r *Responder) Run(ctx context.Context) error {
if summary := readConfigMetadataSummary(r.ConfigPath); summary != nil {
reply.ConfigID = summary.ConfigID
reply.ConfigVersion = summary.ConfigVersion
reply.BusinessName = summary.BusinessName
reply.Template = summary.Template
reply.Profile = summary.Profile
reply.Overlays = copyStringSlice(summary.Overlays)
@ -151,6 +153,7 @@ func split2lines(s string) (string, string, bool) {
type configMetadataSummary struct {
ConfigID string
ConfigVersion string
BusinessName string
Template string
Profile string
Overlays []string
@ -182,6 +185,7 @@ func metadataSummaryFromMap(metadata map[string]any) *configMetadataSummary {
summary := &configMetadataSummary{
ConfigID: stringValue(metadata["config_id"]),
ConfigVersion: stringValue(metadata["config_version"]),
BusinessName: stringValue(metadata["business_name"]),
Template: stringValue(metadata["template"]),
Profile: stringValue(metadata["profile"]),
Overlays: stringSliceValue(metadata["overlays"]),

View File

@ -13,7 +13,7 @@ import (
func TestResponderIncludesConfigSummaryInReply(t *testing.T) {
dir := t.TempDir()
cfgPath := filepath.Join(dir, "media-server.json")
body := []byte(`{"metadata":{"config_id":"cfg-1","config_version":"v1","template":"workshop_face_shoe_alarm","profile":"local_3588_test","overlays":["face_debug"],"instance_names":["cam1"],"instance_display_names":["视觉识别终端-A厂区"]},"instances":[]}`)
body := []byte(`{"metadata":{"config_id":"cfg-1","config_version":"v1","business_name":"A厂区视觉识别","template":"workshop_face_shoe_alarm","profile":"local_3588_test","overlays":["face_debug"],"instance_names":["cam1"],"instance_display_names":["东门入口"]},"instances":[]}`)
if err := os.WriteFile(cfgPath, body, 0o644); err != nil {
t.Fatalf("write config: %v", err)
}
@ -77,7 +77,10 @@ func TestResponderIncludesConfigSummaryInReply(t *testing.T) {
if reply["profile"] != "local_3588_test" {
t.Fatalf("profile = %#v", reply["profile"])
}
if reply["instance_display_name"] != "视觉识别终端-A厂区" {
if reply["business_name"] != "A厂区视觉识别" {
t.Fatalf("business_name = %#v", reply["business_name"])
}
if reply["instance_display_name"] != "东门入口" {
t.Fatalf("instance_display_name = %#v", reply["instance_display_name"])
}
overlays, ok := reply["overlays"].([]any)

View File

@ -46,7 +46,7 @@ func (f fakeProcessController) RollbackBinary(string) (procctl.BinaryUpdateResul
func TestHandleConfigStatusReportsMetadataHashAndMediaStatus(t *testing.T) {
dir := t.TempDir()
cfgPath := filepath.Join(dir, "config.json")
body := []byte(`{"metadata":{"config_id":"cfg-1","config_version":"v1","template":"workshop_face_shoe_alarm","profile":"local_3588_test","overlays":["face_debug"],"instance_names":["cam1"],"instance_display_names":["视觉识别终端-A厂区"]},"instances":[]}`)
body := []byte(`{"metadata":{"config_id":"cfg-1","config_version":"v1","business_name":"A厂区视觉识别","template":"workshop_face_shoe_alarm","profile":"local_3588_test","overlays":["face_debug"],"instance_names":["cam1"],"instance_display_names":["东门入口"]},"instances":[]}`)
if err := os.WriteFile(cfgPath, body, 0o644); err != nil {
t.Fatalf("write config: %v", err)
}
@ -91,7 +91,10 @@ func TestHandleConfigStatusReportsMetadataHashAndMediaStatus(t *testing.T) {
if got["profile"] != "local_3588_test" {
t.Fatalf("profile = %#v", got["profile"])
}
if got["instance_display_name"] != "视觉识别终端-A厂区" {
if got["business_name"] != "A厂区视觉识别" {
t.Fatalf("business_name = %#v", got["business_name"])
}
if got["instance_display_name"] != "东门入口" {
t.Fatalf("instance_display_name = %#v", got["instance_display_name"])
}
overlays, ok := got["overlays"].([]any)
@ -119,7 +122,7 @@ func TestHandleConfigStatusReportsMetadataHashAndMediaStatus(t *testing.T) {
func TestHandleInfoIncludesCurrentConfigSummary(t *testing.T) {
dir := t.TempDir()
cfgPath := filepath.Join(dir, "config.json")
body := []byte(`{"metadata":{"config_id":"cfg-1","config_version":"v1","template":"workshop_face_shoe_alarm","profile":"local_3588_test","overlays":["face_debug","production_quiet"],"instance_names":["cam1"],"instance_display_names":["视觉识别终端-A厂区"]},"instances":[]}`)
body := []byte(`{"metadata":{"config_id":"cfg-1","config_version":"v1","business_name":"A厂区视觉识别","template":"workshop_face_shoe_alarm","profile":"local_3588_test","overlays":["face_debug","production_quiet"],"instance_names":["cam1"],"instance_display_names":["东门入口"]},"instances":[]}`)
if err := os.WriteFile(cfgPath, body, 0o644); err != nil {
t.Fatalf("write config: %v", err)
}
@ -162,7 +165,10 @@ func TestHandleInfoIncludesCurrentConfigSummary(t *testing.T) {
if got["profile"] != "local_3588_test" {
t.Fatalf("profile = %#v", got["profile"])
}
if got["instance_display_name"] != "视觉识别终端-A厂区" {
if got["business_name"] != "A厂区视觉识别" {
t.Fatalf("business_name = %#v", got["business_name"])
}
if got["instance_display_name"] != "东门入口" {
t.Fatalf("instance_display_name = %#v", got["instance_display_name"])
}
overlays, ok := got["overlays"].([]any)

View File

@ -30,6 +30,7 @@ type configFileStatus struct {
type configMetadataSummary struct {
ConfigID string
ConfigVersion string
BusinessName string
Template string
Profile string
Overlays []string
@ -233,6 +234,9 @@ func (s *Server) configStatusPayload() map[string]any {
if summary.ConfigVersion != "" {
resp["config_version"] = summary.ConfigVersion
}
if summary.BusinessName != "" {
resp["business_name"] = summary.BusinessName
}
if summary.Template != "" {
resp["template"] = summary.Template
}
@ -284,6 +288,7 @@ func metadataSummaryFromMap(metadata map[string]any) *configMetadataSummary {
summary := &configMetadataSummary{
ConfigID: stringValue(metadata["config_id"]),
ConfigVersion: stringValue(metadata["config_version"]),
BusinessName: stringValue(metadata["business_name"]),
Template: stringValue(metadata["template"]),
Profile: stringValue(metadata["profile"]),
Overlays: stringSliceValue(metadata["overlays"]),

View File

@ -71,6 +71,7 @@ type InfoResponse struct {
PreviousConfigPath string `json:"previous_config_path"`
ConfigID string `json:"config_id,omitempty"`
ConfigVersion string `json:"config_version,omitempty"`
BusinessName string `json:"business_name,omitempty"`
Template string `json:"template,omitempty"`
Profile string `json:"profile,omitempty"`
Overlays []string `json:"overlays,omitempty"`
@ -178,6 +179,7 @@ func (s *Server) handleInfo(w http.ResponseWriter, r *http.Request) {
if summary := readConfigMetadataSummary(s.agentCfg.ConfigPath); summary != nil {
resp.ConfigID = summary.ConfigID
resp.ConfigVersion = summary.ConfigVersion
resp.BusinessName = summary.BusinessName
resp.Template = summary.Template
resp.Profile = summary.Profile
resp.Overlays = copyStringSlice(summary.Overlays)

View File

@ -1,24 +1,25 @@
{
"name": "local_3588_test",
"description": "Local RK3588 test profile used during workshop face and shoe alarm validation.",
"queue": {
"size": 8,
"strategy": "drop_oldest"
},
"description": "用于B厂的人脸识别和劳保鞋检测",
"business_name": "B厂区视觉识别",
"instances": [
{
"name": "cam1",
"template": "workshop_face_shoe_alarm",
"params": {
"display_name": "视觉识别终端-A厂区",
"channel_no": "cam1",
"device_code": "rk3588-a-001",
"site_name": "A厂区",
"rtsp_url": "rtsp://10.0.0.49:8554/cam",
"display_name": "B厂区通道1",
"publish_hls_path": "./web/hls/cam1/index.m3u8",
"publish_rtsp_port": 8555,
"publish_rtsp_path": "/live/cam1",
"channel_no": "cam1"
"publish_rtsp_port": 8555,
"rtsp_url": "rtsp://10.0.0.49:8554/cam",
"site_name": "B厂区"
},
"template": "workshop_face_shoe_alarm"
}
],
"name": "local_3588_test",
"queue": {
"size": 8,
"strategy": "drop_oldest"
}
}
]
}

View File

@ -305,11 +305,12 @@ class RenderConfigTest(unittest.TestCase):
"""
{
"name": "local_3588_test",
"business_name": "A厂区视觉识别",
"instances": [
{
"name": "cam1",
"params": {
"display_name": "视觉识别终端-A厂区",
"display_name": "东门入口",
"rtsp_url": "rtsp://example/cam1"
}
}
@ -327,8 +328,9 @@ class RenderConfigTest(unittest.TestCase):
)
self.assertEqual(rendered["metadata"]["profile"], "local_3588_test")
self.assertEqual(rendered["metadata"]["business_name"], "A厂区视觉识别")
self.assertEqual(rendered["metadata"]["instance_names"], ["cam1"])
self.assertEqual(rendered["metadata"]["instance_display_names"], ["视觉识别终端-A厂区"])
self.assertEqual(rendered["metadata"]["instance_display_names"], ["东门入口"])
if __name__ == "__main__":

View File

@ -189,6 +189,7 @@ def render(
"template": tpl_name,
"template_path": template_path.as_posix(),
"profile": profile_name,
"business_name": str(profile.get("business_name") or "").strip(),
"profile_path": profile_path.as_posix(),
"instance_names": instance_names,
"instance_display_names": instance_display_names,