NINA 控制 API 文档

1.4 中文深色界面与分级菜单

已按用户提供的参考图改为黑色背景和深灰分层界面。新增观测概览;主控台、设备和序列采用分级菜单,不再集中在一个长页面。中文正文 16px,375 / 390 / 430px 布局与底部导航经过截图复查。设计与信息主次见 docs/UI-DESIGN.md。

分体部署更新到 nina-server-1.4.zip 和 nina-host-1.4.zip,两端同时升级并保留 config.json 与运行数据。域名仍为 https://nina.finderskys.online,现有密钥不变。

1.3 主控台与图形化序列

新增“主控台 / Imaging”页面和多目标图形化序列生成器,继续分为服务器与工控机两个部署包,域名及现有密钥保留。详见 docs/IMAGING.md,其中按 NINA 源码列出已接入功能及 Advanced API 未开放的项目。

支持图像预览、历史与统计、解析、导星曲线、设备附加控制,及常用顺序序列的可视化编排、生成、保存、加载。生成与加载不会自动开始拍摄。

此版不是完整 NINA 桌面克隆,也不冒充支持插件全部节点;未接入项在功能对照中明确列出。

1.2 分体部署与实际拍摄入口

本次正式部署交付为两个包:nina-server-1.2.zip 和 nina-host-1.2.zip,服务器域名已配置为 https://nina.finderskys.online。两个包内 README 分别说明部署操作;详见随包交付的《部署与拍摄说明.md》。

服务器端仅运行转发和网页,工控机端运行 Agent,主动通过 HTTPS 连接服务器;NINA 与 PHD2 保持本机访问。两端保留当前项目的同一对密钥。

新增序列页拍摄监控,每 5 秒读取真实设备和序列状态;可按名称读取、加载 NINA 保存的序列,再单独开始。连续拍摄由 NINA 本地执行,原图保存工控机。

新增只读检查命令 python -m nina_control.preflight --config config.json 和 Windows 当前用户登录任务脚本 install-agent-task.ps1。不自动安装登录任务。

停止命令有独立执行名额,避免四个远程查询或操作等待时阻塞停止。停止序列、曝光、导星和赤道仪是独立命令。

HTTP 命令成功表示 NINA 接受或完成了相应 API 请求,不能用单帧曝光 API 的成功或 IsExposing=false 证明图像已落盘;首次拍摄需要核对 NINA 保存目录中的文件。

该版本未在你的远程服务器或真实设备上验收;Docker、HTTPS 证书签发和真实出片仍需部署后检查。序列 JSON 编辑沿用原生格式,未提供完整拖拽编辑器或原图云端上传下载。

Windows 启动脚本与服务器分离部署步骤见 docs/DEPLOY.md,运行服务后也可打开 /deploy。网页不再按缓存连接状态禁用控制按钮,实际请求交由后端返回结果。

1 连接结构与职责

网页或业务调用方 → HTTPS REST 平台服务器 → 主机主动轮询 → 本机 NINA Advanced API → 已配置的赤道仪驱动。

主机 Agent 每 0.2 秒空闲轮询一次,每 2 秒上报心跳和状态。只使用出站 HTTP 请求,不要求现场开放公网端口。相对长连接,这个首版更容易在代理和断网重连环境下调试;后续可将下行替换为 WebSocket/MQTT,保留 REST 和命令协议不变。方向点动仅在主机与本地 NINA 间使用 WebSocket。

服务器默认为 http://127.0.0.1:18700;联网 Agent 的主机本地 REST 默认为 http://127.0.0.1:18701;单独 host 模式默认 18700。两个 REST 服务提供相同业务接口。远程主机连接强制要求 HTTPS,环回调试允许 HTTP。所有功能只针对一套主机和赤道仪。

2 认证和请求规则

业务请求:Authorization: Bearer <api_token>。网页会记住已填写的密钥,保存在当前浏览器 localStorage;刷新及重新打开页面后自动使用。服务端密钥来自 config.json 或环境变量,不会在重启时自动轮换。

Agent 请求:Authorization: Bearer <agent_token>;注册后还要携带 X-Agent-Session: <session_id>。两种密钥必须不同且至少 32 字符。真实模式不提供无认证控制入口,静态网页和 API 文档可公开读取。

所有改变状态的命令必须携带 Idempotency-Key,长度 8–128。同键同内容返回原命令,同键不同内容返回 409。使用新键表示新的操作;网络超时后应查询旧命令状态,不要换新键重复移动。

POST 使用 JSON;单请求最大 8 MB。跨域请求被拒绝,不启用通配 CORS。默认只接受 localhost/127.0.0.1 Host;部署域名通过 allowed_hosts 配置。反向代理须保留 Host,浏览器与 API 保持同源。HTTP 监听器供本机代理使用,不是 TLS 终止器。

3 业务 REST 接口

方法路径说明
GET/health无密钥存活检查,不代表设备在线
POST/api/v1/session校验已有 Bearer Token,不提供匿名会话或自动登录
GET/api/v1/mount缓存的现场状态;含 agent_online、stale、updated_at、mode、mount
GET/api/v1/mount/capabilities向主机查询驱动能力及点动速率区间
GET/api/v1/targets?q=M31&limit=20向主机读取 NINA 星表,默认最多 20 条,上限 100
POST/api/v1/commands提交命令,202 返回命令记录及 Location
GET/api/v1/commands/{id}查询命令状态、结果或错误
GET/docs中文离线文档
GET/openapi.jsonOpenAPI 3.1 规范

查询结果示例:

{
  "source": "nina_catalog",
  "epoch": "J2000",
  "targets": [{"id":"NGC224","aliases":["M31"],"name":"NGC224","ra_deg":10.6847,"dec_deg":41.2690,"epoch":"J2000","type":"GALXY","source":"nina_catalog"}]
}

示例坐标仅示意返回结构;实际使用主机星表数值。不会请求 NINA 不存在的 /target/search 接口。查询不会移动设备。

4 命令统一格式

POST /api/v1/commands
Authorization: Bearer <api_token>
Idempotency-Key: goto-m31-20261029-001
Content-Type: application/json

{"action":"mount.goto","params":{"ra_deg":10.6847,"dec_deg":41.2690,"epoch":"J2000","tracking":"sidereal"}}
{"id":"<UUID>","action":"mount.goto","params":{},"state":"queued","created":0,"expires":15,"updated":0,"result":null,"error":null}

上例时间字段结构为 Unix 秒,实际响应含完整原始 params。服务器创建的 expires 是 created+15 秒,表示开始执行期限,不表示运动必须 15 秒内完成。Agent 与服务器需进行系统时钟同步。

所有位置输入均为 J2000 赤经角度 ra_deg [0,360)、赤纬 dec_deg [-90,90]。赤经小时须先乘 15。当前不接受 JNOW 输入;NINA 在内部根据驱动完成坐标转换。返回 mount 的坐标可能属于驱动历元,必须同时查看 epoch/raw,不要直接与 J2000 目标做减法。

4.1 赤道仪命令

actionparamsNINA 对应接口
mount.info{}GET /equipment/mount/info
mount.capabilities{}根据 mount/info 提取能力和速率
mount.devices{}GET /equipment/mount/list-devices
mount.rescan{}GET /equipment/mount/rescan
mount.connect可选 device_idGET /equipment/mount/connect?to=...;省略用 NINA 已选设备
mount.disconnect{}GET /equipment/mount/disconnect;转向或跟踪中拒绝
mount.gotora_deg,dec_deg;可选 epoch、trackingGET /equipment/mount/slew;见下一节
mount.stop{}GET /equipment/mount/slew/stop,再停止跟踪
mount.trackingmodeGET /equipment/mount/tracking?mode=...
mount.park{}GET /equipment/mount/park
mount.unpark{}GET /equipment/mount/unpark
mount.set_park{}GET /equipment/mount/set-park-position
mount.home{}GET /equipment/mount/home
mount.syncra_deg,dec_deg;可选 epochGET /equipment/mount/sync;同步坐标模型,不做转向
mount.flip{}GET /equipment/mount/flip;只在 NINA 判定需要时翻转,不强制
mount.jogdirection,rate_deg_s;可选 duration_ms本机 WS /v2/mount,发送 direction/rate

tracking/mode 枚举:sidereal 恒星、lunar 月球、solar 太阳、king King、stopped 停止。对应上游数值 0/1/2/3/4;Goto 不接受 stopped,默认 sidereal。可用模式仍由驱动决定。设置跟踪模式不包含自动寻找相应天体。

Goto 流程:检查已连接、未停放、未转向和必要能力 → 开启指定跟踪 → NINA slew(ra/dec 为角度,center=false、rotate=false、waitForResult=true)→ 再次设置跟踪并读取状态确认。成功表示 NINA 转向返回成功,且读回非 Slewing、TrackingEnabled=true;不是拍照解析居中证明。上游转向请求超时为 180 秒,失败时尝试本地停止,不自动重试。停放设备必须显式 unpark,不会隐式解除停放。

停止不等待 Goto 操作锁。停止命令会取消仍在服务器队列的旧赤道仪控制;主机亦拒绝早于最近停止的旧命令。它是软件停止接口,不能代替硬件急停与现场限位。

park/home/flip 上游会启动异步动作,其命令成功结果标注 completion: accepted_by_nina,只表示 NINA 接受;使用 mount.info 的 AtPark/AtHome/Slewing 等确认物理完成。connect/unpark 等也应读回状态。不要把所有 succeeded 一律解释为设备已停止运动。

点动示例:

{"action":"mount.jog","params":{"direction":"east","rate_deg_s":0.5,"duration_ms":500}}

direction 为 north/south/east/west;速度单位度/秒,非“恒星速倍数”。duration_ms 默认 500,范围 100–1500。请求速率必须在驱动上报区间内;服务上限为 10 度/秒。Agent 每约 0.5 秒续传,结束后发送 0 速,NINA 自身无续传约 2 秒停止。这里是有限时长点动,不能依赖浏览器 mouseup 或远程长按维持运动。

4.2 构图与目标命令

actionparams说明
target.searchquery;可选 limit同目标查询 REST,读取 NINA.sqlite
framing.info{}原样读取 NINA 构图助手信息
framing.setra_deg,dec_deg;可选 epoch、rotation_deg、survey_image设置构图中心与旋转角、回传视场、可选真实底图
framing.sourcesource切换 NINA 构图来源

source 可取 NASA、SKYSERVER、STSCI、ESO、HIPS2FITS、SKYATLAS、FILE、CACHE。NINA 必须至少打开过一次构图助手;set 不执行 slew,不触发相机曝光,不保证 NINA 自己已下载新底图。网页返回的底图由独立 CDS 查询取得,不冒充 NINA 界面截图。

{"action":"framing.set","params":{"ra_deg":10.6847,"dec_deg":41.2690,"epoch":"J2000","rotation_deg":0,"survey_image":true}}

成功 result 包含:

视场公式:width_deg = 2 * atan(width_px * pixel_um / 1000 / (2 * focal_mm)) * 180/pi,高度同理。取 NINA 已有相机和焦距配置,不从浏览器参数臆造设备。参数缺失/非正数返回 FRAMING_NOT_READY。

底图采用固定 CDS HiPS2FITS DSS2 color 服务,800×800,J2000/ICRS 实用近似、TAN 投影,字段范围为相机较大视场的 1.45 倍。网页蓝框显示中心相机视场和构图旋转,是中心视场预览;未实现拼接面板、畸变模型和精密 WCS 拖拽。示意方向为北上东左。运行程序没有模拟模式或模拟回退;无法连接真实 NINA 时返回明确错误,不返回假视场。

5 命令状态与恢复

queued → dispatched → running → succeeded / failed。

queued 超过开始期限由队列认领时标记 expired。进程重启时 dispatched/running 标记 unknown,不自动重放硬件动作。若最终结果超过 240 秒仍未收到,查询时转 unknown,需检查现场。终态不被迟到回报覆盖。

主机日志使用 commandId 去重:网络重试只重传结果,不重新运动。服务器无心跳超过 10 秒判离线,拒绝新命令;状态超过 5 秒标记 stale。服务器重启不重新下发已 dispatch 的命令;Agent 断线不等于设备已经停止。普通 Goto 可能继续在 NINA 内执行,点动有主机时限和 NINA 续传超时。断网期间应在现场 NINA 或主机本地 REST 停止。当前不能保证操作系统崩溃与设备动作之间的严格 exactly-once。

数据库本身已完成 WAL 提交后才派发命令。命令记录没有自动清理策略,应按运营需要离线归档。此版无多租户权限、任务排程、外部天气限位或多机资源调度。

6 Agent 协议

方法路径请求/响应
POST/api/agent/heartbeat{session_id,mode,mount};注册并更新在线状态
POST/api/agent/next{};返回 {command:记录或null},单次领取、不会因 ACK 丢失重发运动
POST/api/agent/commands/{id}{state,result?,error?};上报 running/succeeded/failed/unknown

session_id 每次 Agent 启动重新生成。已有在线会话时拒绝另一实例注册,避免同套设备同时运行两个 Agent。最后一次心跳超过 10 秒后允许新会话接管;旧会话不再可拉取命令。接管前仍需确认旧现场操作是否运行。

7 错误结构

{"error":{"code":"MOUNT_PARKED","message":"Unpark explicitly before moving"}}

HTTP 常见状态:400 参数错误、401 密钥错误、403 来源/Host 错误、404 未知命令、409 状态冲突或上游拒绝、413 请求过大、501 驱动未声明能力、502 上游失败、503 主机/星表不可用、504 查询超时。

异步命令执行错误位于命令记录 error 中,含 code/message/status;查询命令本身仍返回 HTTP 200。NINA 可能 HTTP 200 但 JSON Success=false,本适配器会判为失败,不将其当成功。

8 快速调用

$headers = @{ Authorization = "Bearer $env:NINA_API_TOKEN" }
Invoke-RestMethod 'http://127.0.0.1:18700/api/v1/targets?q=M31' -Headers $headers
$headers['Idempotency-Key'] = [guid]::NewGuid().ToString()
$body = @{ action='mount.goto'; params=@{ra_deg=10.6847; dec_deg=41.2690; epoch='J2000'; tracking='sidereal'} } | ConvertTo-Json
$cmd = Invoke-RestMethod 'http://127.0.0.1:18700/api/v1/commands' -Method Post -Headers $headers -ContentType 'application/json' -Body $body
Invoke-RestMethod "http://127.0.0.1:18700/api/v1/commands/$($cmd.id)" -Headers $headers

9 范围和上游依据

截图所示赤道仪常用功能已覆盖。驱动的物理能力以 capability 为准;未支持的能力不会伪装成功。Advanced API 本身未暴露的厂商私有控制、任意 RA/Dec 自定义跟踪率、脉冲导星、站点写入、驱动设置对话框尚未实现,详见 mount.capabilities 的 unsupported_via_advanced_api。主机不同时直连 ASCOM COM 创建第二个设备控制实例。

上游依据(核对日期 2026-10-29):

本项目使用上游公开协议,未分发 NINA、驱动、其星表或其插件源码。上游 dev 分支会变化,真实联调应记录 /version 返回并核对 API 映射。交付包中的 tests/ 使用隔离的设备替身、伪 NINA 和本地反向连接;生产模块不含模拟设备;不构成 AVX 实机运动验收。

10 设备与序列扩展 1.1

新增功能不改变既有密钥、部署模式或赤道仪接口。仍使用 POST /api/v1/commands 下发 action,202 表示命令已入队;通过返回的 id 查询最终结果。

10.1 设备状态 REST

GET /api/v1/equipment:NINA 全部设备状态原文。

GET /api/v1/camera、/api/v1/filterwheel、/api/v1/focuser、/api/v1/guider:分别读取设备状态。GET /api/v1/guidecamera:通过 PHD2 读取导星相机状态、曝光时间及支持的曝光选项。所有接口均需要 api_token。

设备控制映射如下。参数的必填项以 OpenAPI 为准,带 * 的字段为必填。

actionparams上游接口
camera.info{}/equipment/camera/info
camera.devices{}/equipment/camera/list-devices
camera.rescan{}/equipment/camera/rescan
camera.connectdevice_id/equipment/camera/connect
camera.disconnect{}/equipment/camera/disconnect
filterwheel.info{}/equipment/filterwheel/info
filterwheel.devices{}/equipment/filterwheel/list-devices
filterwheel.rescan{}/equipment/filterwheel/rescan
filterwheel.connectdevice_id/equipment/filterwheel/connect
filterwheel.disconnect{}/equipment/filterwheel/disconnect
focuser.info{}/equipment/focuser/info
focuser.devices{}/equipment/focuser/list-devices
focuser.rescan{}/equipment/focuser/rescan
focuser.connectdevice_id/equipment/focuser/connect
focuser.disconnect{}/equipment/focuser/disconnect
guider.info{}/equipment/guider/info
guider.devices{}/equipment/guider/list-devices
guider.rescan{}/equipment/guider/rescan
guider.connectdevice_id/equipment/guider/connect
guider.disconnect{}/equipment/guider/disconnect
equipment.info{}/equipment/info
camera.captureduration_s*, gain, image_type, save, target_name/equipment/camera/capture
camera.abort{}/equipment/camera/abort-exposure
camera.cooltemperature_c*, minutes, cancel/equipment/camera/cool
camera.warmminutes, cancel/equipment/camera/warm
camera.binningbinning*/equipment/camera/set-binning
camera.readoutmode*/equipment/camera/set-readout
camera.dew_heaterenabled*/equipment/camera/dew-heater
camera.usb_limitlimit*/equipment/camera/usb-limit
camera.statistics{}/equipment/camera/capture/statistics
filterwheel.changefilter_id*/equipment/filterwheel/change-filter
filterwheel.filter_infofilter_id*/equipment/filterwheel/filter-info
focuser.moveposition*/equipment/focuser/move
focuser.stop{}/equipment/focuser/stop-move
focuser.autofocuscancel/equipment/focuser/auto-focus
focuser.last_autofocus{}/equipment/focuser/last-af
guider.startcalibrate/equipment/guider/start
guider.stop{}/equipment/guider/stop
guider.clear_calibration{}/equipment/guider/clear-calibration
guider.graph{}/equipment/guider/graph
guidecamera.info{}本机 PHD2 JSON-RPC
guidecamera.connect{}本机 PHD2 JSON-RPC
guidecamera.disconnect{}本机 PHD2 JSON-RPC
guidecamera.loop{}本机 PHD2 JSON-RPC
guidecamera.stop{}本机 PHD2 JSON-RPC
guidecamera.exposureexposure_ms*本机 PHD2 JSON-RPC
guidecamera.captureexposure_ms本机 PHD2 JSON-RPC
guidecamera.star_imagesize本机 PHD2 JSON-RPC
sequence.list{}主机持久序列库 / NINA 原生 JSON 加载
sequence.getid*主机持久序列库 / NINA 原生 JSON 加载
sequence.createname*, document主机持久序列库 / NINA 原生 JSON 加载
sequence.updateid*, revision*, name, document主机持久序列库 / NINA 原生 JSON 加载
sequence.deleteid*, revision*主机持久序列库 / NINA 原生 JSON 加载
sequence.loadid*, revision*主机持久序列库 / NINA 原生 JSON 加载
sequence.current{}/sequence/json
sequence.state{}/sequence/state
sequence.available{}/sequence/list-available
sequence.start{}/sequence/start
sequence.stop{}/sequence/stop
sequence.reset{}/sequence/reset
sequence.skiptype*/sequence/skip
sequence.load_filename*/sequence/load
sequence.edit_livepath*, value*/sequence/edit
sequence.set_targetname*, ra_deg*, dec_deg*, rotation_deg*, index*/sequence/set-target

10.2 主相机

camera.capture 请求例子:

{"action":"camera.capture","params":{"duration_s":60,"gain":100,"image_type":"LIGHT","save":true,"target_name":"M31"}}

曝光秒数、帧类型、增益由单次 capture 指定;binning 和 readout 通过独立命令设置。不把主相机与导星相机占用同一个硬件实例。原图保存目录由 NINA 配置,接口不返回原图二进制。曝光返回 accepted_by_nina 后用 camera.info 与 camera.statistics 判断真实完成情况;中止使用 camera.abort,停止请求不等待其他操作的控制锁。

制冷 temperature_c 单位摄氏度,minutes 单位分钟,-1 表示 NINA 默认时长;warm 不需要目标温度。驱动不支持某项能力时以真实 NINA 错误为准,不模拟成功。滤镜 ID 以 filterwheel.info 为准;focuser.move 是绝对步数,实际行程以驱动限制为准。自动对焦依赖 NINA 已配置好的相机、滤镜和对焦参数。停止调焦和取消自动对焦是两个独立操作。

10.3 导星相机与 PHD2

NINA guider.* 控制 NINA 已选的导星器:连接、启停、重新校准、读导星误差。guidecamera.* 则直接调用工控机 PHD2 的 JSON-RPC,用于导星相机曝光、循环取像、单帧取像和导星局部图像。

在工控机启动 PHD2,配置真实相机和赤道仪,然后启用“工具 → 启用服务器”。默认 TCP 4400;如第二实例使用其他端口,在 config.json 添加 phd2_port 整数,不需要改变任何已有密钥。所有 PHD2 连接限定 127.0.0.1,不向网页开放原始 TCP。

exposure_ms 单位毫秒,只接受 get_exposure_durations 返回的支持值。单帧取像会让 PHD2 检查当前导星/循环状态;需要时先停止取像。connect/disconnect 对应 PHD2 set_connected,影响其当前配置内全部设备,不是仅对相机做开关。star_image 返回导星星点的局部 16 位图像数据及宽高,不是全幅相机预览。gain、offset 等厂商私有导星相机参数未被 PHD2 JSON-RPC 公开,因此没有虚构接口。

10.4 原生序列库 CRUD

序列文件由工控机持久保存,默认在启动 --data 目录下的 sequences/library.sqlite;可用 config.json 的 sequence_directory 指定其他序列库目录。服务器和 Agent 分开部署时,库仍放在 Agent 工控机上,而不是只存到浏览器或服务器缓存。

方法路径请求体及行为
GET/api/v1/sequences返回库内 id、name、revision、created、updated
POST/api/v1/sequencesname 必填;document 可选;返回异步命令
GET/api/v1/sequences/{id}返回完整原生 document 和当前 revision
PUT 或 PATCH/api/v1/sequences/{id}revision 必填,name/document 至少一个;返回异步命令
DELETE/api/v1/sequences/{id}JSON 请求体含 revision;返回异步命令
POST/api/v1/sequences/{id}/loadJSON 请求体含 revision;加载到 NINA,绝不自动开始

所有写请求需要 Idempotency-Key。也可通过统一命令接口调用同名 sequence.create/get/update/delete/list/load。id 为服务器生成的 32 位小写十六进制标识,不接受文件路径。revision 为乐观锁,更新后加一;版本不匹配返回 REVISION_CONFLICT,防止旧页面覆盖新编辑。

新建示例:

{"action":"sequence.create","params":{"name":"M31 LRGB"}}

省略 document 时生成符合 NINA 容器结构的 Start / Imaging / End 空序列,不包含曝光或运动指令。实际拍摄可在 NINA 保存高级序列 JSON,然后在网页导入、修改原生 JSON 并保存为新序列。网页支持序列列表、读取、JSON 编辑、导入和导出,不提供完整的 NINA 拖拽编辑器。

NINA 原生保存 JSON 包含 $type,并以 SequenceRootContainer 为根。sequence.current 与 sequence.state 是状态快照,不是原生保存文件;服务会拒绝把这类状态结果当成原生序列导入。单序列上限 4 MB。新增自定义插件节点时,工控机 NINA 也必须安装相应插件。服务校验根结构与大小,不替代 NINA 对每个具体节点的验证。

加载指定序列:

{"action":"sequence.load","params":{"id":"返回的32位id","revision":1}}

先在 NINA 打开高级序列器以完成初始化。load 使用 POST /sequence/load,发送未经额外包装的原生 JSON,结果标记 started=false。随后显式调用 sequence.start,保留 skipValidation=false,由 NINA 校验实际设备与序列条件。若 NINA 已在执行序列,加载冲突由 NINA 返回。

sequence.stop 停止 NINA 当前高级序列;sequence.reset 重置当前进度;sequence.skip 可选 CurrentItems/ToEnd/ToImaging。sequence.available 列出 NINA 自己序列目录内的文件;sequence.load_file 只接受这个列表里已有的相对名称,不允许任意路径读取。序列库与 NINA 默认文件目录分开管理:删除库条目不会删除用户原有 NINA 文件,也不会清空已加载的 NINA 副本。更改已保存条目不会直接修改正在执行的副本。

sequence.edit_live 使用 NINA sequence/state 中的路径,支持简单标量字段,是上游实验功能;格式为 Imaging-Items-0-ExposureTime 等。它只修改当前 NINA 内存对象,不自动写回序列库。建议先停止序列再操作,复杂对象/枚举应编辑库中的原生 document 后重新加载。

10.5 来源与验证

接口依据:NINA Advanced API v2 的 api_spec.yaml、Application/Sequence.cs,以及 PHD2 官方事件服务文档:

扩展在隔离的 HTTP/TCP 假上游验证参数、状态和序列读写;没有自动曝光、调焦、切换滤镜或移动真实设备。目标设备与 NINA/PHD2 的实机兼容性仍需现场联调。

11 设备选择与操作反馈修正 1.1.1

网页进入设备页后自动读取设备列表和实时连接状态。相机、滤镜轮、电调焦、导星器和赤道仪均以设备名称显示在下拉框,界面不再要求手工输入 device_id;实际连接时把所选条目的 Id 传给原有 API。可点击刷新设备列表重新获取;没有列表或读取失败时明确显示原因,不会猜测设备 ID。

滤镜轮从 info 的 AvailableFilters 生成滤镜名称下拉框,用 SelectedFilter 显示当前滤镜。选择后自动读取 filter-info,切换前再次核对最新列表,发送实际 Id(支持不连续的编号),切换后读取 SelectedFilter 和 IsMoving 确认到位,不要求用户输入数字。

连接、断开、滤镜切换均显示卡片内反馈、处理中的按钮文案及成功/失败浮动通知。连接/断开由读回的 Connected 状态确认,连接时也核对驱动 DeviceId。12 秒内未确认时显示“请求已接受、状态未确认”,不会把命令接受直接当作连接成功。NINA/PHD2 错误在当前卡片和浮动通知显示。

PHD2 设备连接仍按 PHD2 当前配置执行,不通过 NINA 的 device_id 选择导星相机。该卡片明确显示 PHD2 中配置的相机名称与连接状态。既有 HTTP API、密钥和序列库兼容。

NINA Control 1.3 · 主控台与图形化序列

源码依据与功能边界

已克隆官方仓库到 outputs/nina-upstream,开发版提交 717ea13;同时核对官方 Version-3.2 标签(2393eae581145ed5b8114bf07c48ca2580540fd5)的曝光、等待、制冷和滤镜序列化格式。

本次扩展的是网页和工控机 Agent,没有修改或替换已安装的 NINA 桌面程序。

主控台按 NINA Imaging 的信息面板和工具面板对照实现,连接 NINA Advanced API 2.2.15 系列。

NINA 成像功能网页对应实现说明
当前图像、历史图像真实图像预览、历史点击查看工控机从 NINA 二进制接口取图,经鉴权命令链路回传
缩放、适应、1:1、旋转、十字线浏览器图像工具栏1:1 为预览像素,最大 1280×960,不是传感器全分辨率
九宫格像差检查预览图中心及边角九宫格基于预览采样,不替代原图像差测量
图像拉伸、Debayer跟随 NINA 或手动 factor / blackClipping / unlinked / debayer只影响预览处理,不改原图
图像历史与 HFR 历史历史列表和 HFR / Stars / Mean / Median / StDev / Temperature 曲线图表使用 NINA 返回值;不编造缺失值
图像统计原始 NINA 统计字段HFR、星点数等要求 NINA 自身完成分析
直方图本地 8 位预览亮度直方图明确标注为预览,不冒充原始 ADU 直方图
拍摄、保存开关、中止曝光主控台相机面板图像保存在 NINA 配置目录;接受请求不等于文件已保存
相机制冷、回温、Binning、读出模式、防露、USB 限速相机控制与附加设置实际支持范围由真实相机驱动决定
滤镜轮自动读取名称和位置、切换并确认不手输驱动 ID 或猜测滤镜槽位
电调焦绝对位置、停止、自动对焦、取消、读取 AF 结果对焦曲线原始结果可展开查看
旋转器位置、机械位置、反转、机械范围、停止设备按名称连接
赤道仪连接、停放、解除、零位、跟踪、翻转、停止;目标页 Goto 与同步 API支持范围来自驱动与 Advanced API
导星NINA / PHD2 控制、RA/Dec 曲线、RMS、像素/角秒角秒换算需要 NINA 返回有效 PixelScale
序列状态、开始、停止、重置、原生文件与库管理开始保留 skipValidation=false
开关、天气、安全、平场板、圆顶补充设备面板名称选择连接;开关通道来自真实可写开关列表
图像解析当前图、历史图、拍摄并解析拍摄解析最长 120 秒曝光;不会自动同步或转向
NINA 画面与日志读取 NINA 截图、最近日志、切到成像页截图不是相机图像

以下项目在 NINA 本体源码中存在,但 Advanced API 没有对应控制接口,本次没有宣称完成:原生相机 Live View、ROI 子框、自动 HFR 开关、逐星 HFR 标注、巴氏对焦分析器、自动选取对焦亮星、调焦温度补偿、取消解析、桌面窗口布局控制。也没有把定时刷新预览伪装成相机 Live View。

连续曝光通过 NINA 本地拍摄序列执行;没有引入断线后自动重发的浏览器循环曝光。

若要覆盖上述桌面专属功能,需要另行实现并安装 NINA 扩展插件,不能靠现有 REST 路由假装支持。

图形化生成序列

序列页顶部是图形编辑器。填写计划名称,添加目标,可直接按名称查询工控机 NINA 星表,也可使用目标页已选天体。

坐标输入为 J2000 赤经度数(0..360)与赤纬度数(-90..90),不是赤经小时。多个目标顺序执行。

开始、目标和结束区域均可添加步骤;步骤支持拖动、上移、下移、复制、删除,目标也可调整顺序。

支持的步骤:曝光组、目标转向、解析居中、跟踪设置、自动对焦、开始/停止导星、抖动、等待、制冷、回温、解除停放与停放。

曝光组可选真实滤镜、曝光时间、张数、Gain、Offset、Binning 和帧类型。滤镜 ID 只做接口定位,原生文件使用从 NINA 读回的真实滤镜 Position 和序列化字段。

曝光张数编译为 LoopCondition.Iterations;TakeExposure.ExposureCount 从 0 开始,不把它误用为总张数。

等待时长为秒;温控表单输入秒,生成原生 CoolCamera/WarmCamera.Duration 时转换成分钟。

负赤纬使用 NegativeDec 加有符号 DecDegrees,包含 -0.x° 情况。过中天翻转使用 NINA 自身触发器,需在本机配置翻转参数。

1. “生成 NINA 序列”只编译与校验,显示目标数、曝光张数、纯曝光时间与原生 JSON。

2. “保存到工控机序列库”只保存;“保存并加载”会保存并加载到 NINA,不自动开始。

3. 到主控台或序列监控单独点击“开始”,由 NINA 真实校验后执行。

4. 可导出原生 NINA JSON 或可编辑 .plan.json。草稿也保存在当前浏览器 localStorage。

5. 从序列库读取本工具生成的序列,点击“在图形生成器中编辑”可恢复图形计划,并沿用库条目 revision 更新。

普通 NINA 序列可能包含插件、自定义条件和触发器,不会强行反向转换成有限图形步骤而丢失内容。继续使用原生 JSON 编辑入口。

图形计划嵌入根对象 NinaControlPlan 字段供本工具恢复;NINA 执行的是 Items / Conditions / Triggers 原生结构。

图形器是常用顺序拍摄计划编辑器,不是 NINA 完整节点库:没有并行、嵌套循环编辑、任意插件节点、表达式或完整安全策略的可视化编排。

API

仍使用 POST /api/v1/commands:action=sequence.generate,params={plan:{...}},返回原生 document 和 summary。

它只读取选中滤镜信息,不发送曝光、转向、加载或开始命令。保存继续使用 sequence.create / sequence.update。

新增 image.history / image.preview / image.solve / image.solve_prepared / imaging.capture_solve / application.screenshot / application.logs / application.plugins / application.imaging。

新增 rotator / switch / weather / safetymonitor / flatdevice / dome 的控制路由;通过 GET /api/v1/console/schema 读取表单字段定义。

预览和截图的已完成命令结果仅保留最近 20 个;设备写命令去重记录继续持久保存。

图像以受限尺寸的 data_url 进入原有异步命令结果,不提供任意上游 URL,不开放磁盘路径下载。

所有写操作仍要求独立 API 密钥和 Idempotency-Key。工控机与服务器包必须同时更新。

验证范围

自动化测试覆盖生成文件的循环计数、坐标符号、RA 单位、温控单位、滤镜位置、引用完整性、无曝光/非法步骤拒绝,以及图像流与解析路由。

真实设备、NINA 内部完整反序列化与整夜拍摄仍需在你的工控机验证;当前机器没有 .NET SDK,未编译 NINA 桌面程序。

首次使用先加载生成序列,在 NINA 核对可识别的指令和校验结果,再拍一张短曝光检查保存文件。

源码与文档: