Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
e7c8354
fix: 修复超时门禁单测误伤 asyncio 与间隔抖动 / Fix realtime timeout test breaking as…
YihuiLu Apr 1, 2026
7a18b1c
feat: 调试预览 MJPEG 与 native 直采降内存 / Debug MJPEG preview and native capt…
YihuiLu Apr 1, 2026
9bb7c56
feat: WiFi 切换与调试系统页及网络 API / WiFi switch, debug system page, network API
YihuiLu Apr 1, 2026
7036030
feat: 解算线程池与调试体验更新,修复 WiFi 无线解析 / Solver pool, debug/lab UX, WiFi wir…
YihuiLu Apr 2, 2026
a635be3
feat: WiFi systemd 与安装/解算部署增强 / Enhance WiFi systemd and install/solv…
YihuiLu Apr 2, 2026
0f11708
feat: 电子极轴镜 libcamera AE 预设 / Polar-scope libcamera AE preset
YihuiLu Apr 3, 2026
451008a
fix: 实时解算避免阻塞事件循环以修复长曝光预览卡顿 / Fix realtime solver blocking event loop…
YihuiLu Apr 3, 2026
0641997
fix: AP 热点 shared DHCP 与 WPA2 / AP hotspot shared DHCP and WPA2
YihuiLu Apr 3, 2026
446d228
fix: 调试页默认语言与移动端顶栏 / Debug default locale and mobile header
YihuiLu Apr 3, 2026
90dda05
refactor: 清理遗留预览代码并收紧图像链路 / Tighten image pipeline and remove legacy …
YihuiLu Apr 3, 2026
fbb2f16
feat: 统一开发者控制台 SPA 并完善相机交互 / Unify developer consoles into SPA and po…
YihuiLu Apr 3, 2026
28bb22d
feat: 修复相机控制台文件详情交互并同步构建产物 / Fix camera file detail UX and sync build…
YihuiLu Apr 3, 2026
ae80337
fix: 寻星控制台解算提示占位避免预览抖动 / Reserve gate hint slot to stop preview jitter
YihuiLu Apr 3, 2026
97baec7
chore: 增强安装/升级脚本中图案库与网络同步 / Harden install/update for plate DB and ne…
YihuiLu Apr 3, 2026
dfbcb58
fix: 修复调试素材导入转码进度卡在 18% / Fix debug import transcoding stuck at 18%
YihuiLu Apr 3, 2026
f1aa1ce
fix: Tetra3 数据库加载兼容 NumPy 2 pickle 限制 / Fix Tetra3 DB load with NumPy…
YihuiLu Apr 4, 2026
9f7e2ff
style: Black 格式化以通过 CI / Apply Black formatting for CI
YihuiLu Apr 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ web/analysis-ui/node_modules/
# ====================
# Poetry
# ====================
poetry.lock # 在开发机和 Orange Pi 上可能不一致,建议忽略
poetry.lock # 在开发机与树莓派上可能不一致,建议忽略
.poetry/

# ====================
Expand Down
13 changes: 10 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

## 项目概述

OGScope 是一个基于 Orange Pi Zero 2W 的电子极轴镜系统,用于天文摄影中的精确极轴校准。
OGScope 是一个基于 Raspberry Pi Zero 2W 的电子极轴镜系统,用于天文摄影中的精确极轴校准。

## 技术栈

- **硬件**: Orange Pi Zero 2W, IMX327 相机, 2.4寸 SPI LCD
- **硬件**: Raspberry Pi Zero 2W, IMX327 相机, 2.4寸 SPI LCD
- **语言**: Python 3.9+
- **包管理**: Poetry
- **Web 框架**: FastAPI + Uvicorn
Expand Down Expand Up @@ -93,7 +93,7 @@ ogscope/
- **虚拟环境**: Poetry 管理

### 部署配置
- **生产环境**: Orange Pi Zero 2W 开发板
- **生产环境**: Raspberry Pi Zero 2W 开发板
- **测试环境**: [与生产环境相同]
- **虚拟环境目录**: [用户自定义]

Expand Down Expand Up @@ -123,6 +123,13 @@ WantedBy=multi-user.target

在本地运行时,使用虚拟环境,因为有些硬件只能在开发板上调用,所以本地只是代码编写,远程测试

### WiFi 与网络(NetworkManager)

- **唯一详解**见 [`docs/development/wifi-nm.md`](docs/development/wifi-nm.md):热点默认密码、`network.env`、`/debug/system`、Web API、sudoers(`ogscope-wifi` / `ogscope-nmcli`)等。
- **开机引导**:`ogscope-network-boot.service`(root oneshot,`Before=ogscope.service`)在冷启动时若 STA 长时间无可用 IPv4 则切 **AP**,不依赖 Python 进程。
- **运行时 STA 回滚**:用户通过 Web/API 切 STA 成功后,应用内按 `wifi_sta_rollback_*` 超时无 IPv4 再切回 AP;与开机引导**分工不同、不冲突**(先 boot 完成再启动 `ogscope`)。
- 二者均可能最终执行「切 AP」,行为**幂等**;不建议删除运行时回滚,否则仅冷启动有保障,**运行中**切 STA 失败后需手动恢复。

**重要说明**:
- 系统库(如 `libcamera`、`picamera2`)安装在系统环境中,通过 `PYTHONPATH` 环境变量注入到虚拟环境
- `LD_LIBRARY_PATH` 确保系统库的链接库路径正确
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ lock: ## 锁定依赖版本
build: ## 构建包
poetry build

deploy: ## 部署到 Orange Pi(需要配置 SSH)
@echo "同步代码到 Orange Pi..."
deploy: ## 部署到 Raspberry Pi(需要配置 SSH 主机别名
@echo "同步代码到 Raspberry Pi..."
rsync -avz --exclude '.git' --exclude '__pycache__' --exclude '*.pyc' \
--exclude '.venv' --exclude 'PiFinder-release' \
. orangepi:~/OGScope/
Expand All @@ -69,7 +69,7 @@ logs: ## 查看日志
status: ## 查看服务状态
ssh orangepi "sudo systemctl status ogscope"

ssh: ## SSH 到 Orange Pi
ssh: ## SSH 到 Raspberry Pi(主机名见 Makefile 中 rsync 目标)
ssh orangepi

docs: ## 生成文档(如果使用 Sphinx)
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ poetry shell
python -m ogscope.main
```

开发板一键部署、WiFi 热点与 **`/debug/system`** 等以 [docs/development/wifi-nm.md](docs/development/wifi-nm.md) 与 [docs/development/README.md](docs/development/README.md) 为准。

### Web 界面访问

启动后访问: http://raspberrypi.local:8000 或 http://<IP>:8000
Expand All @@ -89,6 +91,7 @@ python -m ogscope.main
### 开发文档
- [开发指南(中文)](docs/development/README.md)
- [开发指南(English)](docs/development/README_EN.md)
- [树莓派 WiFi / AP / STA / 调试页(NetworkManager)](docs/development/wifi-nm.md)
- [FastAPI 开发](docs/development/fastapi-guide.md)
- [测试指南](docs/development/testing-guide.md)

Expand Down
3 changes: 3 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ poetry shell
python -m ogscope.main
```

On the Raspberry Pi, one-shot deployment, WiFi hotspot, and **`/debug/system`** are documented in [docs/development/wifi-nm.md](docs/development/wifi-nm.md) and [docs/development/README_EN.md](docs/development/README_EN.md).

### Web Interface Access

After startup, visit: http://raspberrypi.local:8000 or http://<IP>:8000
Expand All @@ -89,6 +91,7 @@ After startup, visit: http://raspberrypi.local:8000 or http://<IP>:8000
### Development Documentation
- [Development Guide (English)](docs/development/README_EN.md)
- [Development Guide (中文)](docs/development/README.md)
- [Raspberry Pi WiFi / AP / STA (NetworkManager)](docs/development/wifi-nm.md)
- [FastAPI Development](docs/development/fastapi-guide.md)
- [Testing Guide](docs/development/testing-guide.md)

Expand Down
27 changes: 19 additions & 8 deletions docs/development/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

中文 | [English](README_EN.md)

本文档面向项目成员与协作者,说明 OGScope 在开发板(Raspberry Pi / Orange Pi)环境中的实际运行方式、依赖要求与标准调试流程。
本文档面向项目成员与协作者,说明 OGScope 在 **Raspberry Pi Zero 2W** 等开发板环境中的实际运行方式、依赖要求与标准调试流程。

测试实践请见:[测试指南](testing-guide.md)。

Expand All @@ -15,7 +15,7 @@

### 0.1 系统要求

- 单板:**ARM**(`aarch64` 或 `armhf`),Raspberry Pi / Orange Pi
- 单板:**ARM**(`aarch64` 或 `armhf`),推荐 **Raspberry Pi Zero 2W**
- 系统:**Debian/apt** 系镜像(与 `picamera2`/`libcamera` 文档一致;脚本会读 `/etc/os-release`,见 **§1.4**)
- Python:**3.10+**(以 `pyproject.toml` 为准)
- 网络:首次安装需拉取依赖;浏览器访问 Web 需可达设备 **TCP 8000**(按需防火墙放行)
Expand All @@ -30,11 +30,18 @@ chmod +x scripts/install.sh

说明摘要:默认 `poetry install --only main`;国内网络可 **`export OGSCOPE_MIRROR=cn`**;低配板可 **`OGSCOPE_APT_SLOW=1`**。完整选项见 **§1.4**。安装后:`sudo systemctl start ogscope`。

### 0.3 星图解算数据
### 0.3 网络与 WiFi(AP/STA)

- **`install.sh`** 会安装 `network-manager`、`avahi-daemon`,并执行 **`ogscope-network-init.sh init`**(NM 连接、`/etc/ogscope/network.env`、sudoers、主机名与 `hosts` 等),除非 **`OGSCOPE_SKIP_NETWORK_INIT=1`**。
- 同次安装会写入 **`ogscope-network-boot.service`**(开机无线网络引导:无可用 STA 则回 AP),除非 **`OGSCOPE_SKIP_NETWORK_BOOT=1`**。
- **日常仅同步代码与依赖**优先 **`./scripts/board-update.sh`**;全量重装或改系统级依赖时再跑 **`install.sh`**(见 **§0.5**)。
- 热点 SSID/密码、调试页 **`/debug/system`**、API、**开机引导与运行时 STA 回滚** 的分工:**唯一详解**见 **[wifi-nm.md](wifi-nm.md)**。

### 0.4 星图解算数据

将 **`default_database.npz`** 放到 **`data/plate_solve/`**(不随仓库分发)。放置与配置见 [plate-solve-data.md](plate-solve-data.md)。

### 0.4 日常更新
### 0.5 日常更新

```bash
cd /path/to/OGScope
Expand All @@ -45,7 +52,7 @@ chmod +x scripts/board-update.sh

详情见 **§6.2**。

### 0.5 卸载与健康检查
### 0.6 卸载与健康检查

- 卸载服务与 `.venv`:见 **§6.3**(`scripts/uninstall.sh`)
- 健康检查与日志:
Expand All @@ -56,7 +63,7 @@ sudo systemctl status ogscope
sudo journalctl -u ogscope -f
```

### 0.6 常见故障(简表)
### 0.7 常见故障(简表)

| 现象 | 处理方向 |
|------|----------|
Expand Down Expand Up @@ -99,7 +106,7 @@ poetry install

仓库提供 `scripts/install.sh`,用于在开发板执行一次性环境准备。脚本会:

- 读取 `/etc/os-release` 识别发行版,**仅支持 Debian/Ubuntu 系**(含 **Raspberry Pi OS**、Orange Pi Debian 等);非该系将退出,避免误改软件源
- 读取 `/etc/os-release` 识别发行版,**仅支持 Debian/Ubuntu 系**(含 **Raspberry Pi OS**);非该系将退出,避免误改软件源
- 安装系统依赖与 Poetry
- 配置 Poetry 使用项目 `.venv` 与 `system-site-packages`(Poetry 版本支持时)
- 默认执行 `poetry install --only main`(设 `OGSCOPE_INSTALL_DEV=1` 可装 dev)
Expand Down Expand Up @@ -270,6 +277,7 @@ sudo journalctl -u ogscope -f

- 若仅前端模板/静态文件变更,通常不需要 `poetry install`
- 若服务文件配置有改动,需先 `sudo systemctl daemon-reload`
- 脚本会同步主服务 `ExecStart` 与已安装的 **`ogscope-network-boot.service`** 内 `ExecStart`(项目目录变更时);未安装开机单元则跳过

### 6.3 卸载服务与本地环境(`scripts/uninstall.sh`)

Expand All @@ -278,7 +286,10 @@ sudo journalctl -u ogscope -f
**会执行的操作 / What it does**

- `systemctl stop` / `disable` `ogscope`
- 删除 `/etc/systemd/system/ogscope.service`(若存在),并 `daemon-reload`
- 删除 `/etc/systemd/system/ogscope.service`(若存在)
- 若存在 **`ogscope-network-boot.service`**:`stop` / `disable` 并删除该 unit(与 `install.sh` 安装的引导一致)
- 若存在 **`/etc/systemd/system/ogscope.service.d/ogscope-network-env.conf`**:删除该 drop-in(空目录会尝试 `rmdir`)
- `daemon-reload`
- 默认删除项目根目录下的 **`.venv`**(可用环境变量保留,见下)

**默认保留 / Kept by default**
Expand Down
27 changes: 19 additions & 8 deletions docs/development/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[中文](README.md) | English

This document explains how OGScope is actually run on development boards
(Raspberry Pi / Orange Pi), including dependency requirements, service startup,
(primarily **Raspberry Pi Zero 2W**), including dependency requirements, service startup,
and the team-standard debug workflow.

For testing workflow, see [Testing Guide](testing-guide.md).
Expand All @@ -18,7 +18,7 @@ This section lists **common commands and checks only**. For Poetry/PEP 668, mirr

### 0.1 Requirements

- Board: **ARM** (`aarch64` or `armhf`), e.g. Raspberry Pi / Orange Pi
- Board: **ARM** (`aarch64` or `armhf`), e.g. Raspberry Pi Zero 2W
- OS: **Debian/apt**-based images (compatible with `picamera2`/`libcamera`; install script reads `/etc/os-release`, see **§1.4**)
- Python: **3.10+** (see `pyproject.toml`)
- Network: first install downloads dependencies; Web UI needs **TCP 8000** reachable (configure firewall as needed)
Expand All @@ -33,11 +33,18 @@ chmod +x scripts/install.sh

Summary: default `poetry install --only main`; in mainland China use **`export OGSCOPE_MIRROR=cn`**; low-memory boards: **`OGSCOPE_APT_SLOW=1`**. Full options: **§1.4**. After install: `sudo systemctl start ogscope`.

### 0.3 Plate-solve data
### 0.3 Network and WiFi (AP/STA)

- **`install.sh`** installs `network-manager`, `avahi-daemon`, and runs **`ogscope-network-init.sh init`** (NM profiles, `/etc/ogscope/network.env`, sudoers, hostname/`hosts`, …) unless **`OGSCOPE_SKIP_NETWORK_INIT=1`**.
- The same install writes **`ogscope-network-boot.service`** (boot-time WiFi: fall back to AP if STA has no usable IPv4) unless **`OGSCOPE_SKIP_NETWORK_BOOT=1`**.
- For **routine code and dependency sync**, prefer **`./scripts/board-update.sh`**; rerun **`install.sh`** only for full reinstall or system-level changes (see **§0.5**).
- Hotspot SSID/password, **`/debug/system`**, APIs, and **boot vs runtime STA rollback**: see **[wifi-nm.md](wifi-nm.md)** (authoritative).

### 0.4 Plate-solve data

Place **`default_database.npz`** under **`data/plate_solve/`** (not shipped in the repo). See [plate-solve-data.md](plate-solve-data.md).

### 0.4 Routine updates
### 0.5 Routine updates

```bash
cd /path/to/OGScope
Expand All @@ -48,7 +55,7 @@ chmod +x scripts/board-update.sh

Details: **§6.2**.

### 0.5 Uninstall and health check
### 0.6 Uninstall and health check

- Remove service and `.venv`: **§6.3** (`scripts/uninstall.sh`)
- Health and logs:
Expand All @@ -59,7 +66,7 @@ sudo systemctl status ogscope
sudo journalctl -u ogscope -f
```

### 0.6 Troubleshooting (short)
### 0.7 Troubleshooting (short)

| Symptom | Where to look |
|---------|----------------|
Expand Down Expand Up @@ -279,15 +286,19 @@ Notes:

- if only templates/static files changed, `poetry install` is usually not needed
- if service file changed, run `sudo systemctl daemon-reload` first
- the script syncs **`ExecStart`** for the main `ogscope` unit and, if installed, **`ogscope-network-boot.service`** (when the project directory path changed); if the boot unit was never installed, that step is skipped

### 6.3 Uninstall service and local environment (`scripts/uninstall.sh`)

Use `scripts/uninstall.sh` when you need to **remove the systemd unit**, delete the project **`.venv`**, or clean up before reinstalling in another directory. The script **does not** remove packages installed with `apt` (e.g. `python3-picamera2`) or the user-level **Poetry** installation; it only manages the OGScope service file and optional content under the project tree.
Use `scripts/uninstall.sh` when you need to **remove the systemd unit**, delete the project **`.venv`**, or clean up before reinstalling in another directory. The script **does not** remove packages installed with `apt` (e.g. `python3-picamera2`) or the user-level **Poetry** installation; it removes the OGScope main unit, the optional **network boot** unit and **drop-in** (if present), and optional content under the project tree as described below.

**What it does**

- `systemctl stop` / `disable` `ogscope`
- removes `/etc/systemd/system/ogscope.service` if present, then `daemon-reload`
- removes `/etc/systemd/system/ogscope.service` if present
- if **`ogscope-network-boot.service`** exists: `stop` / `disable` and remove that unit (matches what `install.sh` installs for boot-time WiFi)
- if **`/etc/systemd/system/ogscope.service.d/ogscope-network-env.conf`** exists: remove that drop-in (empty `ogscope.service.d` is removed with `rmdir` when possible)
- `daemon-reload`
- by default removes `.venv` at the project root (can be kept; see below)

**Kept by default**
Expand Down
36 changes: 36 additions & 0 deletions docs/development/ogscope-service-hardening.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# OGScope 服务稳定性与内存防护 / Service stability and memory guard

## systemd 建议(示例,按板子内存调整)/ systemd suggestions (tune MemoryMax per board)

在单元文件 `[Service]` 段可考虑:

- `Restart=always`:进程异常退出后自动拉起 / Auto-restart after exit
- `RestartSec=3`:避免崩溃重启风暴 / Back off between restarts
- `MemoryMax=400M`(示例):限制单服务 RSS,降低拖死整机的概率(Zero2W 请按实际调)/ Cap service RSS to reduce OOM risk

示例片段 / Example snippet:

```ini
[Service]
Restart=always
RestartSec=3
# MemoryMax=400M
```

## OOM 观测 / OOM observation

在设备上可快速确认是否被 OOM killer 终止:

```bash
sudo journalctl -k -b | grep -i -E 'oom|killed process|Out of memory'
sudo dmesg -T | grep -i -E 'oom|killed process'
```

## 与预览相关的环境变量 / Preview-related environment variables

| 变量 / Variable | 含义 / Meaning |
|-----------------|----------------|
| `OGSCOPE_PREVIEW_JPEG_QUALITY` | 共享预览 JPEG 质量(与调试 MJPEG 默认质量一致)/ Shared preview JPEG quality |
| `OGSCOPE_SHARED_PREVIEW_FPS` | 共享抓帧与 MJPEG 推送目标帧率 / Shared grabber and MJPEG pacing FPS |
| `OGSCOPE_DEBUG_PREVIEW_MIN_INTERVAL_MS` | 调试「单帧预览」接口每客户端最小间隔(毫秒);过短返回 304 / Min interval for `/api/debug/camera/preview` per client |
| `OGSCOPE_KEEP_RAW_CACHE` | `1` 时在共享管理器中常驻 `_latest_raw`;默认 `0` 以省内存 / Retain raw frame cache when `1` |
6 changes: 5 additions & 1 deletion docs/development/plate-solve-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

## 2. 获取图案库文件 / Obtaining `default_database.npz`

**自动复制(安装/更新脚本)**:若 `ogscope/vendor/tetra3/data/default_database.npz` 已存在,或 Poetry 解析到的 `tetra3` 包内带有该文件,`scripts/install.sh` 与 `scripts/board-update.sh` 会将其复制到 `data/plate_solve/default_database.npz`(目标已存在则跳过;覆盖用 `OGSCOPE_FORCE_PLATE_DB=1`;跳过整步用 `OGSCOPE_SKIP_PLATE_DB=1`)。

**Auto-copy (install/update scripts)**: If `ogscope/vendor/tetra3/data/default_database.npz` exists, or the resolved `tetra3` package ships it, `scripts/install.sh` and `scripts/board-update.sh` copy it to `data/plate_solve/default_database.npz` (skip if dest exists; `OGSCOPE_FORCE_PLATE_DB=1` to overwrite; `OGSCOPE_SKIP_PLATE_DB=1` to skip).

任选其一:

1. **从 PyPI `cedar-solve` wheel 提取**
Expand Down Expand Up @@ -55,5 +59,5 @@

## 7. 性能提示 / Performance

- Orange Pi 等资源受限设备:可适当**降低分辨率**、限制 `solver_max_stars`、拉大 `solver_fullsolve_interval_frames`(实时模式)。
- Raspberry Pi Zero 2W 等资源受限设备:可适当**降低分辨率**、限制 `solver_max_stars`、拉大 `solver_fullsolve_interval_frames`(实时模式)。
- Tetra 解算在后台线程执行,避免阻塞事件循环(见 `asyncio.to_thread`)。
Loading
Loading