Files
hospital-front-agent/agent/config.py
T
lianlonggangandClaude f07bbbc49d feat: RESTART 走 NSSM 服务重启 + 失败原因可观测化
- RESTART 命令优先通过 nssm restart 重启主程序服务(假死场景可用),未配置服务名回退环回 HTTP
- nssm 输出按 UTF-16 解码并记录日志,权限不足时提示需以服务方式运行
- 环回管理接口 code=3001 时明确报鉴权失败,不再误报不可达
- 新增 nssm.path / main.service.name / log.dir 配置项
- 增加文件日志(RotatingFileHandler 5MB×5),服务方式运行可查日志
- HTTP 调用失败与状态码异常统一 WARNING 记录(原 DEBUG 不可见)
- 断线日志区分「网络不通」与「被服务器拒绝(未注册/token 错误)」
- 连接 URL 自动拼接 device.id,消除双处配置不一致

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-27 17:24:17 +08:00

81 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""Agent 配置加载。
从 conf/agent.properties 读取(key=value),支持环境变量覆盖(AGENT_ 前缀大写)。
配置项:
- server.url B 端 WebSocket 地址(经网关转发,须带 /medical 服务前缀)
- device.id 设备编号(医院唯一,如 jinghe-01)
- device.token 设备鉴权 Token
- main.health.url 主程序健康检查地址(http://127.0.0.1:8082/api/admin/health
- main.admin.token 主程序管理接口 Token(与主程序 admin.token 一致)
- main.start.cmd 主程序启动命令(Windows: bin\\start.batLinux: bin/start.sh
- nssm.path NSSM 可执行文件路径(配置 main.service.name 时用于拉起服务)
- main.service.name 主程序注册的 Windows 服务名(配置后看门狗用 nssm restart 拉起,优先于 main.start.cmd
- heartbeat.sec 心跳间隔(默认 15 秒,须小于网关空闲超时)
- guard.enable 是否守护主程序(默认 true)
- log.dir 日志目录(默认 logs,相对部署根目录)
"""
import os
from dataclasses import dataclass
@dataclass
class AgentConfig:
"""Agent 全量配置(不可变)。"""
server_url: str
device_id: str
device_token: str
main_health_url: str
main_admin_token: str
main_start_cmd: str
nssm_path: str
main_service_name: str
heartbeat_sec: int
guard_enabled: bool
log_dir: str
@classmethod
def load(cls, conf_path: str = "conf/agent.properties") -> "AgentConfig":
"""从指定路径加载配置,环境变量优先。"""
props = {}
if os.path.exists(conf_path):
try:
with open(conf_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
# 跳过空行与注释
if not line or line.startswith("#"):
continue
if "=" in line:
key, _, value = line.partition("=")
props[key.strip()] = value.strip()
except Exception:
# 读取失败时按空配置处理,交由各配置项默认值兜底
pass
return cls(
server_url=_get(props, "server.url", "ws://127.0.0.1:19901/medical/agentSocket/unknown-device"),
device_id=_get(props, "device.id", "unknown-device"),
device_token=_get(props, "device.token", ""),
main_health_url=_get(props, "main.health.url", "http://127.0.0.1:8082/api/admin/health"),
main_admin_token=_get(props, "main.admin.token", ""),
main_start_cmd=_get(props, "main.start.cmd", "bin/start.bat"),
nssm_path=_get(props, "nssm.path", ""),
main_service_name=_get(props, "main.service.name", ""),
heartbeat_sec=int(_get(props, "heartbeat.sec", "15")),
guard_enabled=_get(props, "guard.enable", "true").lower() == "true",
log_dir=_get(props, "log.dir", "logs"),
)
def _get(props: dict, key: str, default: str) -> str:
"""读取单个配置项:环境变量 > properties > 默认值。"""
env_key = "AGENT_" + key.replace(".", "_").upper()
env = os.environ.get(env_key)
if env is not None:
return env
return props.get(key, default)