diff --git a/Sense/README.md b/Sense/README.md index f732326..a85022a 100644 --- a/Sense/README.md +++ b/Sense/README.md @@ -53,3 +53,18 @@ corepack pnpm@9.15.1 build The frontend automatically discovers project-local route and store modules. Feature tickets add one route module without exposing unrelated GoAdmin demo pages. + +## Windows package + +With the frozen Go toolchain first in `PATH`, build the backend, frontend and +ZIP archive with one command from the repository root: + +```powershell +cmd /c .\Sense\scripts\package-windows.bat +``` + +The ignored local artifact is `Sense\dist\sense-windows-amd64.zip`. It contains +the Windows amd64 server, compiled UI, empty example configuration, upstream +licenses, a start script and an operations note. Run `start-sense.bat demo` only +for a temporary local preview; production startup requires externally supplied +PostgreSQL and secret environment variables. diff --git a/Sense/config/sense.env.example b/Sense/config/sense.env.example index 8a216bd..12630c7 100644 --- a/Sense/config/sense.env.example +++ b/Sense/config/sense.env.example @@ -4,4 +4,12 @@ SENSE_DATABASE_MODE=postgres SENSE_DATABASE_URL= SENSE_LOG_LEVEL=info SENSE_UI_STATIC_DIR= - +SENSE_IDENTITY_SIGNING_KEY= +SENSE_BOOTSTRAP_TOKEN= +SENSE_COOKIE_SECURE=true +SENSE_CREDENTIAL_KEY= +SENSE_ONVIF_DISCOVERY_IP= +SENSE_MEDIAMTX_BINARY= +SENSE_MEDIAMTX_CONFIG= +SENSE_MEDIAMTX_API=http://127.0.0.1:9997 +SENSE_MEDIAMTX_WEBRTC_BASE=http://127.0.0.1:8889 diff --git a/Sense/scripts/package-windows.bat b/Sense/scripts/package-windows.bat new file mode 100644 index 0000000..04fd475 --- /dev/null +++ b/Sense/scripts/package-windows.bat @@ -0,0 +1,93 @@ +@echo off +setlocal + +for %%I in ("%~dp0..") do set "SENSE_ROOT=%%~fI" +for %%I in ("%SENSE_ROOT%\dist") do set "OUTPUT_ROOT=%%~fI" +for %%I in ("%OUTPUT_ROOT%\sense-windows-amd64") do set "PACKAGE_DIR=%%~fI" +for %%I in ("%OUTPUT_ROOT%\sense-windows-amd64.zip") do set "ZIP_PATH=%%~fI" +for %%I in ("%SENSE_ROOT%\ui\dist") do set "UI_DIST=%%~fI" + +if /I not "%PACKAGE_DIR%"=="%SENSE_ROOT%\dist\sense-windows-amd64" ( + echo [ERROR] Unsafe package directory: %PACKAGE_DIR% + exit /b 1 +) +if /I not "%ZIP_PATH%"=="%SENSE_ROOT%\dist\sense-windows-amd64.zip" ( + echo [ERROR] Unsafe ZIP path: %ZIP_PATH% + exit /b 1 +) + +where go >nul 2>nul || goto :missing_go +for /f "tokens=3" %%V in ('go version') do set "GO_VERSION=%%V" +if not "%GO_VERSION%"=="go1.26.5" ( + echo [ERROR] Go 1.26.5 is required, found %GO_VERSION%. + exit /b 1 +) + +where node >nul 2>nul || goto :missing_node +for /f "delims=" %%V in ('node --version') do set "NODE_VERSION=%%V" +if not "%NODE_VERSION%"=="v22.22.1" ( + echo [ERROR] Node.js 22.22.1 is required, found %NODE_VERSION%. + exit /b 1 +) + +where corepack >nul 2>nul || goto :missing_corepack +for /f "delims=" %%V in ('corepack pnpm@9.15.1 --version') do set "PNPM_VERSION=%%V" +if not "%PNPM_VERSION%"=="9.15.1" ( + echo [ERROR] pnpm 9.15.1 is required, found %PNPM_VERSION%. + exit /b 1 +) + +echo [1/5] Installing frozen frontend dependencies... +pushd "%SENSE_ROOT%\ui" || goto :failed +call corepack pnpm@9.15.1 install --frozen-lockfile || goto :failed_popd + +echo [2/5] Building frontend... +call corepack pnpm@9.15.1 build || goto :failed_popd +popd + +if exist "%PACKAGE_DIR%" rmdir /s /q "%PACKAGE_DIR%" +if exist "%ZIP_PATH%" del /q "%ZIP_PATH%" +mkdir "%PACKAGE_DIR%\config" || goto :failed + +echo [3/5] Building Windows backend... +set "CGO_ENABLED=0" +set "GOOS=windows" +set "GOARCH=amd64" +pushd "%SENSE_ROOT%\server" || goto :failed +go build -trimpath -ldflags "-s -w" -o "%PACKAGE_DIR%\sense-server.exe" . || goto :failed_popd +popd + +echo [4/5] Assembling package... +robocopy "%UI_DIST%" "%PACKAGE_DIR%\ui" /E /NFL /NDL /NJH /NJS /NP >nul +if errorlevel 8 goto :failed +robocopy "%SENSE_ROOT%\LICENSES" "%PACKAGE_DIR%\LICENSES" /E /NFL /NDL /NJH /NJS /NP >nul +if errorlevel 8 goto :failed +copy /y "%SENSE_ROOT%\config\sense.env.example" "%PACKAGE_DIR%\config\sense.env.example" >nul || goto :failed +copy /y "%SENSE_ROOT%\scripts\runtime\start-sense.bat" "%PACKAGE_DIR%\start-sense.bat" >nul || goto :failed +copy /y "%SENSE_ROOT%\scripts\runtime\README-WINDOWS.md" "%PACKAGE_DIR%\README-WINDOWS.md" >nul || goto :failed + +echo [5/5] Creating ZIP... +powershell -NoProfile -ExecutionPolicy Bypass -Command "Compress-Archive -Path '%PACKAGE_DIR%' -DestinationPath '%ZIP_PATH%' -Force" || goto :failed + +echo. +echo Package directory: %PACKAGE_DIR% +echo ZIP archive: %ZIP_PATH% +exit /b 0 + +:failed_popd +popd +:failed +echo [ERROR] Packaging failed. +exit /b 1 + +:missing_go +echo [ERROR] Go was not found in PATH. +exit /b 1 + +:missing_node +echo [ERROR] Node.js was not found in PATH. +exit /b 1 + +:missing_corepack +echo [ERROR] Corepack was not found in PATH. +exit /b 1 diff --git a/Sense/scripts/runtime/README-WINDOWS.md b/Sense/scripts/runtime/README-WINDOWS.md new file mode 100644 index 0000000..3bd3ae6 --- /dev/null +++ b/Sense/scripts/runtime/README-WINDOWS.md @@ -0,0 +1,32 @@ +# Sense Windows 运行包 + +此目录同时包含 Sense 后端和已经构建好的前端静态页面。Brain、Bell 无需启动。 + +## 快速查看 + +在命令提示符中运行: + +```bat +start-sense.bat demo +``` + +然后访问 。`demo` 使用内存数据,进程退出后数据会丢失,仅用于本机查看,不能用于生产。 + +## 生产启动 + +生产环境必须先安装并准备独立 PostgreSQL,然后在仓库和运行包之外安全设置以下环境变量: + +- `SENSE_DATABASE_URL`:PostgreSQL 连接地址。 +- `SENSE_IDENTITY_SIGNING_KEY`:至少 32 个字符的会话签名密钥。 +- `SENSE_BOOTSTRAP_TOKEN`:首次初始化使用的引导令牌。 +- `SENSE_CREDENTIAL_KEY`:Base64 编码的 32 字节摄像头凭据加密密钥。 + +按需要设置 `SENSE_HTTP_ADDRESS`、MediaMTX 和 ONVIF 参数后运行: + +```bat +start-sense.bat +``` + +完整变量名可参考 `config\sense.env.example`。示例文件只有空值和非秘密默认值,启动脚本不会自动读取它;请使用 Windows 环境变量或外部秘密管理工具注入真实值。 + +健康检查为 `GET /healthz` 和 `GET /readyz`。MediaMTX 仍是独立程序,本运行包不会安装 PostgreSQL、MediaMTX 或 Windows 服务。 diff --git a/Sense/scripts/runtime/start-sense.bat b/Sense/scripts/runtime/start-sense.bat new file mode 100644 index 0000000..4e6c9ab --- /dev/null +++ b/Sense/scripts/runtime/start-sense.bat @@ -0,0 +1,45 @@ +@echo off +setlocal +cd /d "%~dp0" + +set "SENSE_UI_STATIC_DIR=%~dp0ui" + +if /I "%~1"=="demo" goto :demo + +set "SENSE_DATABASE_MODE=postgres" +if "%SENSE_DATABASE_URL%"=="" goto :missing_database_url +if "%SENSE_IDENTITY_SIGNING_KEY%"=="" goto :missing_identity_key +if "%SENSE_BOOTSTRAP_TOKEN%"=="" goto :missing_bootstrap_token +if "%SENSE_CREDENTIAL_KEY%"=="" goto :missing_credential_key + +echo Starting Sense in production mode at %SENSE_HTTP_ADDRESS%... +"%~dp0sense-server.exe" +exit /b %ERRORLEVEL% + +:demo +set "SENSE_DATABASE_MODE=memory" +if "%SENSE_HTTP_ADDRESS%"=="" set "SENSE_HTTP_ADDRESS=127.0.0.1:18080" +echo Starting Sense in temporary demo mode at http://%SENSE_HTTP_ADDRESS% ... +echo Demo data is discarded when the process stops. Do not use this mode in production. +"%~dp0sense-server.exe" +exit /b %ERRORLEVEL% + +:missing_database_url +echo [ERROR] SENSE_DATABASE_URL is required in production mode. +goto :configuration_help + +:missing_identity_key +echo [ERROR] SENSE_IDENTITY_SIGNING_KEY is required in production mode. +goto :configuration_help + +:missing_bootstrap_token +echo [ERROR] SENSE_BOOTSTRAP_TOKEN is required in production mode. +goto :configuration_help + +:missing_credential_key +echo [ERROR] SENSE_CREDENTIAL_KEY is required in production mode. + +:configuration_help +echo Set the required environment variables outside this directory. +echo See README-WINDOWS.md and config\sense.env.example. +exit /b 1