--- name: tou-template-scheduling description: 编写、校验并保存 FranklinWH 的 TOU(分时电价)调度模板,用于 EMS 调度配置。当用户需要构建、编辑、理解或上传 TOU 电价模板时使用——包括时段策略、光伏/负载优先级、充放电功率限制、省/市选择等。涵盖 updateOrSaveIotTouTemplate 请求体以及 MCP 工具 service_tou_template_*。 --- # FranklinWH TOU 调度模板 用于构建并保存 EMS 调度(TOU)模板。一个模板 = 基础信息 + 一个或多个「季节/日类型」策略;每个策略 = 覆盖一整天的时段列表。它对应云端 `updateOrSaveIotTouTemplate` 接口和设备侧 355/357 调度协议。 参考资料(完整协议与字段语义): `/home/jerry-remote/web/FranklinWH-Wiki/client/docs/Software/ScriptingForSchedulingConfiguration.md` 字段权威定义(Go DTO):`service/dto/fwhTestTouTemplateDTO.go` --- ## MCP 工具 所有工具都接受可选参数 `env`:`pro`(生产)或 `test`(测试)。 | 工具 | 用途 | env 默认值 | | ----------------------------- | -------------------------------------------- | -------------------- | | `service_tou_template_list` | 查询模板列表(按类型/状态/关键字筛选) | `pro` | | `service_tou_template_detail` | 按`id` 查询单个模板详情 | `pro` | | `service_tou_template_save` | 新增/更新模板,返回 templateId**【写操作】** | `test`(当前仅支持) | | `service_tou_template_cites` | 查询某国家下的省/市列表 | `test`(当前仅支持) | save 与 cites 目前仅支持 `test`。读操作默认走 `pro`,需要读测试环境时传 `env:"test"`。 典型流程:`cites`(拿 countryId/provinceId)→ 构建 payload → `save` → `detail` 校验。 --- ## 请求体结构(`service_tou_template_save` 的 `payload`) 顶层结构(`FwhTestUpdateOrSaveTouTemplatePayload`): ```json { "template": { /* 模板主体,见下表 */ }, "strategyList": [ { /* 策略,见下表 */ } ], "lang": "ZH_CN" } ``` - 所有字段都是 JSON **字符串**。数值型字段以「字符串形式的数字」传递;**未设置的字段传空串 `""`**(不要传 `null`)。 - `template.templateId`:**创建模板时不需要此字段(省略);更新模板时必须带此字段并填入模板 ID**。读取(`detail`/`list` 返回)时该字段必定存在。 - `template.sourceType`:**必填**。当前**仅允许写入系统模板 `"0"`**(`1`API模板 / `2`用户推荐 暂不支持写入,`save` 会拒绝)。 ### 1. `template`(模板主体 · `FwhTestTouTemplateInfo`) | 字段 | 类型 | 含义 / 取值 | | -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------- | | `countryId` | string(数值) | 国家 ID | | `provinceId` | string(数值) | 州/省 ID | | `derSchdule` | string | DER 调度配置 | | `eleCompanyFullName` | string | 电力公司全称 | | `electricCompany` | string | 电力公司(简称) | | `gridType` | string | 电网类型 / 套餐类型 | | `electricityType` | string(数值) | 电价类型:`1`分时电价 `2`阶梯电价 `3`固定电价 `4`分时&阶梯电价 `5`BB套餐 `6`Peak Demand | | `name` | string | 模板/策略表名称 | | `mookRunCount` | string(数值) | 模式执行次数(loop):`0`不限次数 `1`执行一次 | | `priority` | string(数值) | 模式优先级,默认`0`;`0` 最低,数字越大优先级越高 | | `env` | string(数值·位域) | 模式使用条件,默认`0`;bit0~1 光伏;bit2~3 馈网;bit4~5 电网充电 | | `templateId` | string(数值) | 模板 ID。**创建时不需要(省略此字段);更新时必须带上并填 ID**。读取(detail/list)返回时该字段必定存在 | | `sourceType` | string(数值·必填) | 模板类型。**必填,当前仅允许 `0`系统模板**(`1`API模板 `2`用户推荐 暂不支持写入) | ### 2. `strategyList[]`(策略 · `FwhTestTouTemplateStrategy`) 一个策略 = 一组「季节/日类型」+ 覆盖一整天的时段列表。 | 字段 | 类型 | 含义 / 取值 | | -------------- | ------------ | ---------------------------------------------------------------- | | `ccociateType` | string(数值) | 关联类型编码,如`1` | | `ccociateSn` | string | 关联设备 SN(无则空串) | | `detailVoList` | array | 时段明细表,**所有时段必须覆盖一整天**(见下表) | | `seasonName` | string | 季节名,用于标识策略范围,可自定义,如`summer`、`All months` | | `month` | string | 逗号分隔的月份,如`1,2,3,4,5,6,7,8,9,10,11,12` | | `dayName` | string | 日期类型可读名称,如`Every day`、`Weekdays`(与 `dayType` 对应) | | `dayType` | string(数值) | 日期类型编码:`1`工作日 `2`节假日 `3`每天(可读名见 `dayName`) | ### 3. `detailVoList[]`(时段明细 · `FwhTestTouTemplateDetailVo`) 同一策略内的所有时段必须铺满一整天:每个 `endHourTime` 等于下一段的 `startHourTime`,第一段是 `00:00`,最后一段是 `24:00`。值均为字符串,`""` 表示未设置(勿传 `null`)。 | 字段 | 类型 | 含义 / 取值 | | ------------------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `startHourTime` | string | 开始时间,格式`HH:mm`,如 `06:30` | | `endHourTime` | string | 结束时间,格式`HH:mm`;需与下一段 `startHourTime` 衔接,所有时段覆盖一整天 | | `waveType` | string(数值·flag) | 峰平谷定义:`0`谷/off-peak `1`平/mid-peak `2`峰/on-peak `3`尖峰/super-on-peak `4`低谷/super-off-peak | | `name` | string | 时段名,一般为`supper-off-peak`、`off-peak`、`mid-peak`、`on-peak`、`supper-on-peak` 等 | | `briefDescribe` | string | 时段描述,如`Self-consumption` | | `solarPriority` | string | **光伏供电优先级**,格式 `"市电,负载,FHP"`,如 `"1,3,2"`;优先级 `0/1/2/3`,可相同(表示按比例/功率分配),`0`=不涉及,数字越大优先级越高 | | `loadPriority` | string | **负载取电优先级**,格式 `"市电,光伏,FHP"`,如 `"1,3,2"`;优先级 `0/1/2/3`,可相同(按比例/功率分配),`0`=不使用此源,数字越大优先级越高 | | `gridDischargeMax` | string(kW,0.1) | 电池最大允许馈网功率;可选,默认`0` 不能馈网;`0`不可馈网,`-1`不限制 | | `gridChargeMax` | string(kW,0.1) | 电网允许最大充电功率;可选,默认`0` 不允许;`0`不允许,`-1`不限制 | | `chargePower` | string(kW,0.1) | 固定电池充电功率,按单台功率计算;可选,默认`-1` 未设置 | | `dischargePower` | string(kW,0.1) | 固定电池放电功率,按单台功率计算;可选,默认`-1` 未设置 | | `chargeMax` | string(kW,0.1) | 电池最大允许充电功率,按单台功率计算;`-1`无限制,默认 `-1` | | `dischargeMax` | string(kW,0.1) | 电池最大允许放电功率,按单台功率计算;`-1`无限制,默认 `-1` | | `gcaoMax` | string(kW,0.1) | GCAO(grid charge after an outage):停电后补电至预留 SOC 的单台市电取电功率;可选;`0`不允许,`-1`不限制;默认未设置(`-3`);使能后未设值则为 `5kw*N`(用 `-2` 标识) | | `gridFeedMax` | string(kW,0.1) | 电网允许最大馈网功率;可选,默认`-2`;`0`不允许,`-1`不限制,`-2`未设置 | | `gridMax` | string(kW,0.1) | 电网允许最大取电功率;可选,默认`-1` 不限制;`0`不允许,`-1`不限制 | | `minDischargeSoc` | string(%,整数) | 放电截止 SOC;达到此 SOC 后电池不放电,可选,默认`0%`;若 `reserved_soc` 大于此值则以 `reserved_soc` 为准 | | `maxChargeSoc` | string(%,整数) | 充电截止 SOC;可选,默认`100%` | | `heatEnable` | string(数值) | 充电加热使能:`0`未设置(默认) `1`不使能 `2`使能 | | `powerOffApower` | string(数值) | 主动关闭 APower;可选,`0`不控制(默认) `1`关机 `2`开机(预留) | | `rampTime` | string(秒) | 爬坡时间,`0~300`;默认 `0`,BB套餐默认 `300` | | `offGrid` | string(数值) | 主动断开市电继电器:`0`不控制(默认) `1`断开 `2`闭合(预留) | | `solarCutoff` | string(数值) | 主动断开光伏继电器:`0`不控制(默认) `1`断开 `2`闭合(预留) | **要点**: - `solarPriority` / `loadPriority` 是 3 值字符串,顺序 `[市电, 负载或光伏, FHP/aPower]`;`0`=不参与,数字越大优先级越高,相同非 0 值=按比例分配。 - 功率字段单位 **kW、精度 0.1**,按单台 aPower 计(总功率 = 值 × 台数 N):`gridChargeMax`、`gridDischargeMax`、`gridFeedMax`、`gridMax`、`chargePower`、`dischargePower`、`chargeMax`、`dischargeMax`、`gcaoMax`。常见哨兵值:`-1`不限制、`0`不允许/不可、`-2`未设置(仅 `gridFeedMax`/`gcaoMax`)、`-3`未设置(仅 `gcaoMax`)。 ### 完整 detailVoList 单段示例 ```json { "startHourTime": "00:00", "endHourTime": "11:00", "waveType": "1", "name": "mid-peak", "briefDescribe": "Self-consumption", "solarPriority": "1,3,2", "loadPriority": "1,3,2", "gridChargeMax": "", "gridDischargeMax": "", "gridFeedMax": "", "gridMax": "", "chargePower": "", "dischargePower": "", "chargeMax": "", "dischargeMax": "", "gcaoMax": "", "minDischargeSoc": "", "maxChargeSoc": "", "heatEnable": "", "rampTime": "", "offGrid": "", "solarCutoff": "0", "powerOffApower": "" } ``` ### selectCitesList 返回结构(`service_tou_template_cites`) `FwhTestCitesListData`:`countryList` / `provinceList` / `cityList` 三个数组。各项字段(注意此接口返回中 `id` 为**数值**,非字符串): | 结构 | 字段 | | --------------------- | -------------------------------------------------------------------- | | `FwhTestCountryInfo` | `id`(int), `nameEn`, `nameZh`, `latitude`, `longitude` | | `FwhTestProvinceInfo` | `id`(int), `nameEn`, `nameZh`, `latitude`, `longitude`, `cityList[]` | | `FwhTestCityInfo` | `id`(int), `nameEn`, `nameZh`, `latitude`, `longitude` | --- ## 优先级 → 调度策略 速查 常见 `solarPriority`/`loadPriority` 组合及其含义(来自 `templateTable.vue`): | 光伏优先级 | 负载优先级 | 策略 | | ---------- | ---------- | ------------------------------------------------------------- | | `1,2,0` | `1,3,2` | A | | `1,2,0` | `1,2,0` | B —— 电池不参与调度(光伏优先供载,剩余馈网,市电补充) | | `1,3,2` | `1,2,0` | C —— 光伏剩余充电(光伏优先供载,剩余给电池充电,电池不放电) | | `1,3,2` | `1,3,2` | D —— 自发自用(标准,最常用) | | `1,2,3` | `1,2,0` | E/G —— 光伏优先充电 | | `1,2,0` | `1,2,3` | F/H —— 电池优先供载 | 标准模板(来自 wiki《常规调度配置》): - **自发自用**:`solarPriority:"1,3,2"`,`loadPriority:"1,3,2"`,describe `"Self-consumption"`。 - **仅备电**:`gridChargeMax:"-1"`(不限充),`chargePower:"8"`(约 8kW 满充),describe `"Emergency backup"`。 - **强制放电/馈网收益**:`gridDischargeMax:"-1"`(不限馈网),`dischargePower:"10"`(约 10kW 满放)。 --- ## 规则 1. **时间覆盖**:每个策略的 `detailVoList` 必须覆盖 00:00→24:00,无空档、无重叠;`endHourTime` == 下一段 `startHourTime`;时间格式 `HH:mm`。 2. **未设置传 ""**:明细字段绝不传 `null`,用空串;数字也以字符串形式传。 3. **功率单位是 kW**(步进 0.1),按单台 aPower 计。不要对这些模板字段套用设备侧的 W 或 `5kw*N/-2` 约定。 4. **优先级是 3 值字符串** `"a,b,c"`,顺序为 `[市电, 负载/光伏, aPower]`。 5. **新增 vs 更新**:`template.templateId` 留空为新增;填入 ID 为更新。 6. **写操作走 `test`**:`service_tou_template_save` 仅支持 `env:"test"`。保存前先与用户确认(会修改服务器数据)。保存后用 `service_tou_template_detail`(带 `env:"test"`)校验。 7. 执行写操作前,需要和用户确认最终写入或更新的信息,确认后才能调用 `service_tou_template_save` 创建或更新 8. 不确定某国家的 `provinceId` 时,先调用 `service_tou_template_cites` 传 `country_id`。 --- ## 示例流程:构建一个标准自发自用模板 1. `service_tou_template_cites { "country_id": 3 }` → 选出 `provinceId`。 2. 构建一个策略(dayType 3 = 每天),用策略 D(`solarPriority:"1,3,2"`,`loadPriority:"1,3,2"`)铺一整天单一时段,或拆成 off/mid/on-peak 多个时段。 3. `service_tou_template_save { "env":"test", "payload": "" }` → 记下返回的 `templateId`。 4. `service_tou_template_detail { "env":"test", "id": }` 确认结果。