# JDF Energy Collector 小时能源数据采集程序。程序定时从能源管理系统接口查询上一小时点位数据,通过 `addpointdatum` 接口写入基础数据服务,然后触发 `calc_agg_points_range` 计算聚合接口。 ## 数据流程 1. 启动时读取 `config.yaml`。 2. 启动时读取 `points.csv`,建立能源系统 `id` 到平台 `point_id` 的映射。 3. 每小时在 `schedule.minute` 配置的分钟执行一次。 4. 调用能源系统登录接口获取 token,默认 6 小时复用一次。 5. 查询上一小时数据。 6. 过滤无效数据并组装 `addpointdatum` 请求。 7. `addpointdatum` 写入成功后,调用 calcagg 回算。 ## 环境要求 - Python 3.10+ - Poetry 依赖见 `pyproject.toml`: ```text PyYAML requests ``` ## 安装 ```bash poetry install ``` ## 配置 默认配置文件为 `config.yaml`。 示例: ```yaml energy_chaowang: base_url: "http://127.0.0.1:8089" username: "dt" password: "dt2026" login_timeout_seconds: 5 query_timeout_seconds: 10 token_refresh_interval_hours: 6 points: file: "points.csv" services: basedataportal: "http://192.168.1.109:18503" calcagg: "http://192.168.1.109:42941" schedule: minute: 31 logging: file: "logs/jdf-energy-collector.log" retention_days: 3 ``` 配置说明: | 配置项 | 说明 | | --- | --- | | `energy_chaowang.base_url` | 能源管理系统基础地址 | | `energy_chaowang.username` | 登录用户名 | | `energy_chaowang.password` | 登录密码 | | `energy_chaowang.login_timeout_seconds` | 登录接口超时时间 | | `energy_chaowang.query_timeout_seconds` | 小时数据查询接口超时时间 | | `energy_chaowang.token_refresh_interval_hours` | token 复用时长,默认 6 小时 | | `points.file` | 点位 CSV 文件路径 | | `services.basedataportal` | 基础数据服务基础地址,会拼接 `/ai/addpointdatum` | | `services.calcagg` | 计算聚合服务基础地址,会拼接 `/api/calcagg/calc_agg_points_range` | | `schedule.minute` | 每小时第几分钟执行,范围 0 到 59 | | `logging.file` | 日志文件路径 | | `logging.retention_days` | 日志保留天数 | ## 点位文件 `points.csv` 使用 UTF-8 编码和英文逗号分隔,必须包含两列: | 列名 | 说明 | | --- | --- | | `id` | 能源管理系统点位 id,用于查询接口的 `tagNameList` | | `point_id` | 平台点位编码,用于 `addpointdatum` 和 calcagg | 程序启动时会校验: - `id` 不能重复 - `point_id` 不能重复 - 至少存在一条有效点位 ## 运行 使用默认配置: ```bash poetry run python main.py ``` 指定配置文件: ```bash poetry run python main.py --config config.yaml ``` 程序为常驻进程,会持续等待下一次调度时间执行。 ## 接口调用 ### 登录接口 地址: ```text {energy_chaowang.base_url}/api/thingshome-admin/sys/service/getToken ``` 登录失败最多重试 3 次,每次间隔 60 秒。 ### 小时数据查询接口 地址: ```text {energy_chaowang.base_url}/api/thingshome-ems/realTime/selectByCustom ``` 查询范围为上一小时: - `startTime`: 当前整点减 1 小时 - `endTime`: 当前整点减 1 秒 - `dateCode`: `h` - `energyTypeList`: `['electric power']` 查询 timeout 时最多重试 3 次,每次间隔 10 秒。 ### addpointdatum 写入接口 地址: ```text {services.basedataportal}/ai/addpointdatum ``` 请求体示例: ```json [ { "point_id": "TEST_POINT_DIFF_H", "data": [ { "ts": 1781770962, "value": "49.97" } ] } ] ``` 写入规则: - `id` 未在 `points.csv` 配置时跳过。 - `fullTime` 或 `thisValue` 缺失时跳过。 - `thisValue == 0` 时跳过。 - `fullTime` 转换为秒级时间戳后作为 `ts`。 - `thisValue` 转为字符串后作为 `value`。 - 接口返回 `state != 0` 时本轮失败,不继续调用 calcagg。 默认超时为 5 秒。 ### calcagg 回算接口 地址: ```text {services.calcagg}/api/calcagg/calc_agg_points_range ``` 请求体示例: ```json { "end": 1781773199, "begin": 1781769600, "sync_run": true, "point_ids": [ "TEST_POINT_DIFF_H" ], "operator_name": "jdf-energy-collector" } ``` calcagg 只会在 `addpointdatum` 成功写入至少一个点位后调用。 ## 日志 日志同时输出到控制台和 `logging.file` 配置的文件。 HTTP 请求会打印: - 请求名称 - URL - timeout - headers - payload - HTTP 状态码 - 响应体 - 耗时 `elapsed_ms` 敏感字段会脱敏: - `authorization` - `password` - `token` `addpointdatum` 的完整请求体会打印在日志中。点位较多时,单条日志会比较长。 ## 验证 语法检查: ```bash python -m py_compile main.py ```