修改平台名称和界面,增加了项目介绍文档和部分代码注释;为申请软著增加的代码文件。
This commit is contained in:
parent
7a2e82db0d
commit
2921c180cb
162
docs/project_info.md
Normal file
162
docs/project_info.md
Normal file
@ -0,0 +1,162 @@
|
||||
# 工业安全生产视觉监测平台——项目信息
|
||||
|
||||
## 摘要
|
||||
|
||||
本平台由**管理后台**和**边缘计算节点**两部分组成。管理后台基于 **Go 1.23** 开发,部署于 Windows 环境,采用 SQLite 嵌入式数据库,前端使用 Tabler CSS 框架及服务端模板渲染。边缘节点运行于 **RK3588 ARM Linux**,核心分析引擎用 **C++17** 实现,通过 NPU/VPU/RGA 硬件加速进行实时视频 AI 推理;设备管理代理用 **Go 1.21** 开发,负责与管理后台通信。平台总代码量 **109,924 行**,覆盖设备管理、AI 模型部署、人脸识别、劳保用品合规检测、告警联动等完整功能链路。
|
||||
|
||||
---
|
||||
|
||||
## 一、管理后台(managerd)
|
||||
|
||||
### 1. 软件开发环境/开发工具
|
||||
|
||||
| 类别 | 详情 |
|
||||
|------|------|
|
||||
| 编程语言 | Go 1.23.3 |
|
||||
| IDE/编辑器 | VS Code / Cursor |
|
||||
| 构建工具 | Go build + PowerShell 脚本(scripts/managerd.ps1) |
|
||||
| 版本控制 | Git |
|
||||
| 开发操作系统 | Windows 11 |
|
||||
|
||||
### 2. 软件运行支撑环境/支持软件
|
||||
|
||||
| 类别 | 详情 |
|
||||
|------|------|
|
||||
| 运行时 | Go 编译为单一可执行文件(managerd.exe),无需额外运行时 |
|
||||
| 操作系统 | Windows(服务端) |
|
||||
| 数据库 | SQLite(嵌入式数据库,modernc.org/sqlite 纯 Go 驱动) |
|
||||
| Web 框架 | go-chi/chi v5.2.3(HTTP 路由) |
|
||||
| 前端框架 | Tabler CSS + 原生 JavaScript(服务端模板渲染) |
|
||||
| 浏览器 | Chrome / Edge / Firefox 等现代浏览器 |
|
||||
| 依赖库 | chi(路由)、cors(跨域)、uuid(标识生成) |
|
||||
|
||||
### 3. 编程语言
|
||||
|
||||
**Go**(版本 1.23.3)
|
||||
|
||||
### 4. 代码行数
|
||||
|
||||
| 类型 | 文件数 | 总行数 |
|
||||
|------|--------|--------|
|
||||
| Go 源码 | 59 个 | 23,500 行 |
|
||||
| 前端模板(HTML/CSS) | 62 个 | 6,675 行 |
|
||||
| JSON 配置文件 | 19 个 | — |
|
||||
| 核心文件 `internal/web/ui.go` | 1 个 | 4,861 行 |
|
||||
|
||||
### 5. 软件架构
|
||||
|
||||
```
|
||||
cmd/managerd/main.go —— 组装入口,手动依赖注入
|
||||
internal/api/ —— HTTP API 处理器(chi router)
|
||||
internal/web/ —— Web UI 处理器 + 嵌入式前端模板
|
||||
internal/service/ —— 业务逻辑层
|
||||
internal/storage/ —— SQLite 数据持久层
|
||||
internal/config/ —— JSON 配置文件加载
|
||||
internal/models/ —— 核心领域模型
|
||||
templates/ —— 本地 JSON 模板文件
|
||||
```
|
||||
|
||||
### 6. 主要模块
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| 仪表盘 | 设备统计、在线率、告警概览、异常设备、最近任务 |
|
||||
| 管控台 | 设备能力矩阵、视频源分配、通道管理 |
|
||||
| 设备管理 | 局域网设备发现、注册、在线监控、批量操作 |
|
||||
| 设备控制 | 配置预览、应用下发、服务控制、模型上传 |
|
||||
| 告警中心 | 告警采集、分页查询、规则中文翻译 |
|
||||
| 人脸库 | 人员注册、照片管理、人脸库构建与下发 |
|
||||
| 视频监控 | 多路视频推流代理(HLS/RTSP) |
|
||||
| 任务中心 | 批量任务创建、执行、状态追踪 |
|
||||
| 配置中心 | 模板/场景/视频源/第三方服务/调试参数管理 |
|
||||
| 模型管理 | AI 模型概览与设备同步 |
|
||||
| 场景管理 | 场景配置编辑、视频通道、通道部署 |
|
||||
| 系统设置 | 数据备份恢复、服务状态、日志审计 |
|
||||
|
||||
---
|
||||
|
||||
## 二、边缘计算节点(RK3588)
|
||||
|
||||
### 1. 软件开发环境/开发工具
|
||||
|
||||
| 类别 | 详情 |
|
||||
|------|------|
|
||||
| 编程语言 | C++17(媒体分析引擎)、Go 1.21(设备代理) |
|
||||
| 构建系统 | CMake 3.20+(C++)、Go build(Agent) |
|
||||
| 交叉编译 | Ubuntu 22.04 ARM64 工具链,aarch64-linux-gnu-g++ |
|
||||
| IDE/编辑器 | VS Code |
|
||||
| 版本控制 | Git |
|
||||
| 开发/运行平台 | Orange Pi 5 Plus(RK3588)、Ubuntu 22.04 |
|
||||
|
||||
### 2. 软件运行支撑环境/支持软件
|
||||
|
||||
| 类别 | 详情 |
|
||||
|------|------|
|
||||
| 操作系统 | Ubuntu 22.04(ARM64) |
|
||||
| 硬件平台 | 瑞芯微 RK3588(8 核 CPU + 6 TOPS NPU + VPU + RGA) |
|
||||
| AI 推理框架 | RKNN Toolkit 2(Rockchip 官方 NPU 推理框架) |
|
||||
| 硬件加速 | MPP(Media Process Platform,硬编解码)、RGA(图像缩放/颜色转换) |
|
||||
| 视频协议 | RTSP 输入、RTSP/HLS 输出 |
|
||||
| 流媒体 | FFmpeg(软件编解码备选) |
|
||||
| 存储 | MinIO(对象存储,抓拍与录像片段) |
|
||||
| 编译依赖 | CMake、GCC/G++(ARM64 交叉编译或本地编译) |
|
||||
| 进程管理 | systemd(media-server.service、rk3588-agent.service) |
|
||||
|
||||
### 3. 编程语言
|
||||
|
||||
- **C++17**(媒体分析引擎,核心 AI 推理管线)
|
||||
- **Go 1.21**(设备管理代理 rk3588-agent)
|
||||
- **Python**(模型训练、数据预处理、模型转换工具)
|
||||
|
||||
### 4. 代码行数
|
||||
|
||||
| 组件 | 语言 | 文件数 | 行数 |
|
||||
|------|------|--------|------|
|
||||
| 媒体分析引擎 | C++17 | 200+ | 61,531 行 |
|
||||
| 设备管理代理 | Go 1.21 | 41 个 | 7,251 行 |
|
||||
| 工具脚本 | Python | 51 个 | 10,967 行 |
|
||||
| **合计** | | **300+** | **79,749 行** |
|
||||
|
||||
### 5. 软件架构
|
||||
|
||||
```
|
||||
agent/ —— Go 设备代理:HTTP API、进程管理、度量采集
|
||||
internal/
|
||||
httpapi/ —— REST API 服务(端口 9100)
|
||||
mediaserver/ —— 媒体服务管理(启动/停止/状态)
|
||||
metrics/ —— CPU/NPU/内存/磁盘指标采集
|
||||
modelstore/ —— AI 模型文件管理
|
||||
procctl/ —— 进程控制
|
||||
tasks/ —— 任务执行
|
||||
src/ —— C++ 媒体分析引擎
|
||||
plugins/ —— AI 分析插件(人脸检测/识别、人员检测/跟踪、工鞋检测等)
|
||||
ai_scrfd_sliding/ —— 滑窗人脸检测
|
||||
ai_face_recog/ —— 人脸识别
|
||||
ai_yolo/ —— YOLO 目标检测
|
||||
ai_shoe_det/ —— 劳保鞋检测
|
||||
tracker/ —— ByteTrack 多目标跟踪
|
||||
logic_gate/ —— 业务规则(人鞋关联、颜色判定)
|
||||
alarm/ —— 告警上报
|
||||
osd/ —— 画面叠加
|
||||
publish/ —— 视频推流
|
||||
```
|
||||
|
||||
### 6. AI 分析管线
|
||||
|
||||
| 管线 | 说明 |
|
||||
|------|------|
|
||||
| 人脸识别 | RTSP 输入 → 预处理 → SCRFD 滑窗人脸检测 → MobileFaceNet 人脸识别 → OSD → HLS/RTSP 输出 |
|
||||
| 劳保鞋检测 | RTSP 输入 → YOLO 人员检测 → ByteTrack 跟踪 → 动态 ROI 鞋检测 → 人鞋关联 → 颜色判定 → 告警 |
|
||||
| 全功能车间 | 人脸检测 + 人脸识别 + 人员检测 + 跟踪 + 劳保鞋合规 + OSD + 视频发布 + 告警上报 + 抓拍存证 |
|
||||
|
||||
---
|
||||
|
||||
## 三、系统总览
|
||||
|
||||
| 项目 | 管理后台 | 边缘节点 | 合计 |
|
||||
|------|----------|----------|------|
|
||||
| 语言 | Go | C++17 + Go + Python | 3 种 |
|
||||
| 代码行数 | 30,175 行 | 79,749 行 | **109,924 行** |
|
||||
| 文件数 | 140 个 | 300+ 个 | **440+ 个** |
|
||||
| 运行平台 | Windows | Ubuntu ARM64 | — |
|
||||
| 数据库 | SQLite | — | SQLite |
|
||||
1912
docs/source_code_p1_35.txt
Normal file
1912
docs/source_code_p1_35.txt
Normal file
File diff suppressed because it is too large
Load Diff
1924
docs/source_code_p31_65.txt
Normal file
1924
docs/source_code_p31_65.txt
Normal file
File diff suppressed because it is too large
Load Diff
132
extract_src.go
Normal file
132
extract_src.go
Normal file
@ -0,0 +1,132 @@
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Module definitions: line number ranges and their descriptions
|
||||
type Module struct {
|
||||
Start int // inclusive 1-indexed
|
||||
End int // inclusive 1-indexed
|
||||
Title string
|
||||
Comment string
|
||||
}
|
||||
|
||||
var modules = []Module{
|
||||
{1, 26, "包声明与依赖导入", "程序入口包声明及标准库、项目内部包、第三方库导入"},
|
||||
{27, 48, "核心数据结构 UI", "UI 结构体,聚合所有服务依赖,是 Web 层的核心中枢"},
|
||||
{49, 170, "页面数据模型 PageData", "统一的页面渲染数据载体,包含设备、任务、告警、配置等所有页面所需数据"},
|
||||
{171, 222, "辅助视图类型", "DeviceOverviewRow、TaskDeviceRow、ConfigStatusView 等轻量视图模型"},
|
||||
{223, 545, "构造函数与模板函数注册", "NewUI 创建 UI 实例,注册模板渲染所需的 FuncMap(JSON序列化、类型标签、规则映射等)"},
|
||||
{546, 625, "依赖注入方法", "SetStateRepo、SetAuditRepo、SetAlarmCollector 等延迟注入方法"},
|
||||
{626, 762, "路由注册 Routes", "将 HTTP 路径映射到对应的页面处理函数和 API 动作函数"},
|
||||
{763, 825, "模板渲染与设备工具方法", "render 模板渲染、findDevice 设备查找、ensureDevicesLoaded 缓存加载"},
|
||||
{826, 895, "仪表盘页面", "pageDashboard 渲染系统总览:设备统计、告警概览、异常设备、最近任务"},
|
||||
{896, 1244, "管控台页面", "pageConsole 设备能力矩阵展示、actionConsoleSave 保存管控配置"},
|
||||
{1245, 1410, "设备列表与批量操作", "pageDevices 列表、actionDeviceAdd 添加、actionDiscoverySearch 发现、actionDevicesBatchAction 批量操作"},
|
||||
{1410, 1726, "设备详情与单设备控制", "pageDevice 详情、pageDeviceControl 控制、actionDeviceAction 下发动作、actionDeviceConfigApply 配置应用"},
|
||||
{1727, 1833, "任务管理模块", "pageTasks 列表、taskPageData 数据、actionCreateTask 创建任务、pageTask 详情"},
|
||||
{1834, 1913, "模型管理", "pageModels 模型概览、actionModelSync 同步模型到设备"},
|
||||
{1914, 2004, "告警与诊断", "pageDiagnostics 诊断页、pageAlarms 告警中心(分页过滤)"},
|
||||
{2005, 2066, "资源管理", "pageResources 资源概览、actionResourceSync 资源同步"},
|
||||
{2067, 2133, "配置资产管理——模板", "pageAssetTemplates 列表、CRUD 操作"},
|
||||
{2134, 2475, "配置资产管理——模板操作", "actionAssetTemplateCreate 创建、Clone 克隆、Rename 重命名、Delete 删除、GraphSave 可视化保存、Export 导出"},
|
||||
{2476, 2748, "场景配置与视频通道", "pagePlan/pageAssetProfiles 场景管理、pageRecognitionUnits 视频通道、CRUD"},
|
||||
{2749, 2856, "通道部署与设备分配", "pageDeviceAssignments 部署矩阵、actionDeviceAssignmentSave/Delete 分配操作"},
|
||||
{2857, 3038, "视频源与第三方服务", "pageAssetVideoSources 视频源管理、pageAssetIntegrations 集成服务管理、CRUD"},
|
||||
{3039, 3209, "调试参数管理", "pageAssetOverlays 调试参数列表、actionAssetOverlaySave/Clone/Delete"},
|
||||
{3210, 3600, "配置预览与格式转换", "assetPageData 跨页共享数据、profileEditor 场景编辑器、configPreview 配置预览渲染"},
|
||||
{3601, 4414, "设备配置交互 UI", "pageDeviceConfigUI/Friendly 友好配置页面、configPreviewPageData 预览、actionDeviceConfigUIPlan/Apply 应用下发"},
|
||||
{4415, 4476, "人脸库上传与设备代理", "actionDeviceFaceGalleryUpload 上传人脸图片、actionDeviceFaceGalleryReload 重新加载人脸库"},
|
||||
{4477, 4652, "视频监控与人脸库管理", "pageMonitor 监控页、proxyHLS 代理推流、actionFaceGalleryAdd/Build 人脸库构建"},
|
||||
{4653, 4822, "人脸库页面与设备指标 API", "pageFaceGallery 人脸库展示、serveFacePhoto 照片服务、apiDeviceMetrics 指标接口"},
|
||||
{4823, 4863, "控制台视图模型", "DeviceMetric、ConsoleDeviceData、ConsoleChannel、ConsoleFeature 等控制台用数据结构"},
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Fprintln(os.Stderr, "Usage: go run extract_src.go <source.go>")
|
||||
os.Exit(1)
|
||||
}
|
||||
srcPath := os.Args[1]
|
||||
|
||||
f, err := os.Open(srcPath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var lines []string
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
|
||||
outPath := "docs/source_code.md"
|
||||
out, err := os.Create(outPath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
w := bufio.NewWriter(out)
|
||||
|
||||
// Header
|
||||
w.WriteString("# 工业安全生产视觉监测平台——核心源代码\n\n")
|
||||
w.WriteString("**软件名称**:工业安全生产视觉监测平台\n")
|
||||
w.WriteString("**版本**:V1.0\n")
|
||||
w.WriteString("**开发语言**:Go\n")
|
||||
w.WriteString("**源文件**:`internal/web/ui.go`\n")
|
||||
w.WriteString("**总行数**:" + fmt.Sprintf("%d", len(lines)) + "\n\n")
|
||||
w.WriteString("---\n\n")
|
||||
w.WriteString("## 模块概览\n\n")
|
||||
for _, m := range modules {
|
||||
w.WriteString(fmt.Sprintf("- **%s**(第 %d-%d 行):%s\n", m.Title, m.Start, m.End, m.Comment))
|
||||
}
|
||||
w.WriteString("\n---\n\n")
|
||||
|
||||
// Find function/type boundaries for better formatting
|
||||
typeBoundaryRe := regexp.MustCompile(`^(func |type )`)
|
||||
commentRe := regexp.MustCompile(`^//`) // Sometimes we use // comments
|
||||
|
||||
moduleIdx := 0
|
||||
for i, line := range lines {
|
||||
lineNum := i + 1
|
||||
|
||||
// Check if we need to start a new module section
|
||||
for moduleIdx < len(modules) && lineNum == modules[moduleIdx].Start {
|
||||
m := modules[moduleIdx]
|
||||
w.WriteString(fmt.Sprintf("## 模块 %d:%s\n", moduleIdx+1, m.Title))
|
||||
w.WriteString(fmt.Sprintf("> %s\n\n", m.Comment))
|
||||
w.WriteString("```go\n")
|
||||
moduleIdx++
|
||||
}
|
||||
|
||||
// Check if we need to close a module section
|
||||
if moduleIdx > 0 && lineNum == modules[moduleIdx-1].End+1 {
|
||||
w.WriteString("```\n\n")
|
||||
}
|
||||
|
||||
// Mark important type/function boundaries (but these are already covered by modules)
|
||||
_ = typeBoundaryRe
|
||||
_ = commentRe
|
||||
|
||||
w.WriteString(line + "\n")
|
||||
}
|
||||
|
||||
// Close last module if needed
|
||||
if moduleIdx > 0 && moduleIdx <= len(modules) {
|
||||
w.WriteString("```\n\n")
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
fmt.Printf("Done: %s (%d lines)\n", outPath, len(lines))
|
||||
}
|
||||
@ -46,8 +46,12 @@ const (
|
||||
deviceAssignmentPreviewDeviceCount = 8
|
||||
)
|
||||
|
||||
const version = "1.0"
|
||||
|
||||
type PageData struct {
|
||||
Title string
|
||||
Version string
|
||||
Year int
|
||||
ContentHTML template.HTML
|
||||
Message string
|
||||
Error string
|
||||
@ -270,6 +274,20 @@ func NewUI(discovery *service.DiscoveryService, registry *service.RegistryServic
|
||||
return v
|
||||
}
|
||||
},
|
||||
"ruleLabel": func(v string) string {
|
||||
switch strings.TrimSpace(v) {
|
||||
case "unknown_face":
|
||||
return "陌生人员告警"
|
||||
case "known_person":
|
||||
return "已登记人员"
|
||||
case "non_compliant_workshoe":
|
||||
return "未穿劳保鞋"
|
||||
case "non_black_shoe":
|
||||
return "工鞋不合规"
|
||||
default:
|
||||
return v
|
||||
}
|
||||
},
|
||||
"displayDeviceName": func(dev *models.Device, status *ConfigStatusView) string {
|
||||
if dev == nil {
|
||||
return "-"
|
||||
@ -743,6 +761,8 @@ func (u *UI) Routes() (chi.Router, error) {
|
||||
}
|
||||
|
||||
func (u *UI) render(w http.ResponseWriter, r *http.Request, content string, data PageData) {
|
||||
data.Version = version
|
||||
data.Year = time.Now().Year()
|
||||
var buf bytes.Buffer
|
||||
if err := u.tpl.ExecuteTemplate(&buf, content, data); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
||||
@ -118,7 +118,7 @@ code,.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
||||
|
||||
.app-shell{display:grid;grid-template-columns:240px minmax(0,1fr);min-height:100vh}
|
||||
.sidebar{background:var(--sidebar);color:var(--sidebar-text);display:flex;flex-direction:column;padding:18px 14px;position:sticky;top:0;height:100vh}
|
||||
.brand-block{display:flex;gap:12px;align-items:center;padding:4px 8px 20px}
|
||||
.brand-block{display:flex;gap:8px;align-items:center;padding:4px 0 20px 4px;margin-left:-8px}
|
||||
.brand-mark{width:38px;height:38px;border-radius:var(--radius);background:rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.12);display:grid;place-items:center;font-size:13px;font-weight:600;color:var(--primary)}
|
||||
.brand-title{font-size:14px;font-weight:600}
|
||||
.side-nav{display:flex;flex-direction:column;gap:4px}
|
||||
@ -431,3 +431,5 @@ pre{margin-top:12px;padding:12px;border-radius:var(--radius);border:1px solid va
|
||||
.assignment-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}
|
||||
.assignment-board-grid{grid-template-columns:1fr}
|
||||
}
|
||||
|
||||
.sidebar-footer{margin-top:auto;padding:16px 8px 0;border-top:1px solid rgba(255,255,255,.08);font-size:11px;color:var(--sidebar-muted);line-height:1.6;text-align:center}
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
</td>
|
||||
<td>{{.Channel}}</td>
|
||||
<td>
|
||||
<span class="pill warn">{{.RuleName}}</span>
|
||||
<span class="pill warn">{{ruleLabel .RuleName}}</span>
|
||||
</td>
|
||||
<td>{{if .ObjectLabel}}{{.ObjectLabel}}{{else}}-{{end}}</td>
|
||||
<td>{{if .Confidence}}{{printf "%.2f" .Confidence}}{{else}}-{{end}}</td>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<div style="display:flex;flex-wrap:wrap;gap:8px">
|
||||
{{range .AlarmRecords}}
|
||||
<div style="padding:8px 12px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-soft);min-width:200px">
|
||||
<div style="font-weight:500;font-size:12px;margin-bottom:2px">{{.RuleName}}</div>
|
||||
<div style="font-weight:500;font-size:12px;margin-bottom:2px">{{ruleLabel .RuleName}}</div>
|
||||
<div class="muted small mono">{{.Timestamp}}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<div class="brand-block">
|
||||
<div class="brand-mark">AI</div>
|
||||
<div>
|
||||
<div class="brand-title">视觉识别运维平台</div>
|
||||
<div class="brand-title">工业安全生产视觉监测平台</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="side-nav" aria-label="主导航">
|
||||
@ -44,6 +44,10 @@
|
||||
</div>
|
||||
</details>
|
||||
</nav>
|
||||
<div class="sidebar-footer">
|
||||
<div>北京泰奥理科技有限公司</div>
|
||||
<div>© {{.Year}} V{{.Version}}</div>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="workspace">
|
||||
<header class="topbar">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user