# 充电桩数据同步实现计划 > 创建时间:2025-12-30 > 任务状态:规划中 --- ## 一、需求概述 将 Web 项目(MySQL)中的充电桩数据同步到 JCPP 项目(PostgreSQL)中,用于登录鉴权等操作。 ### 1.1 数据流向 ``` Web 项目 (MySQL) → JCPP 项目 (PostgreSQL) ``` ### 1.2 同步方式 - **全量同步**:同步所有充电桩和充电枪数据 - **增量同步**:只同步新增或修改的数据(基于 update_time) --- ## 二、表结构映射分析 ### 2.1 充电桩表映射 | Web 字段 (pile_basic_info) | JCPP 字段 (t_pile) | 映射说明 | |---------------------------|-------------------|---------| | id (int) | - | Web 主键,不同步 | | sn (varchar(20)) | pile_code (varchar(255)) | 充电桩编码,唯一标识 | | name (varchar(32)) | pile_name (varchar(255)) | 充电桩名称 | | software_protocol (varchar(20)) | protocol (varchar(255)) | 软件协议 | | station_id (int) | station_id (uuid) | ✅ 统一使用固定值 '88bca8da-cdbf-6587-aecc-75784838c501' | | model_id (int) | model (varchar(255)) | 型号,需要查询转换 | | - | brand (varchar(255)) | 品牌,可为空 | | - | manufacturer (varchar(255)) | 制造商,可为空 | | business_type (char(5)) | type (varchar(16)) | 经营类型映射 | | 其他字段 | additional_info (jsonb) | 存储为 JSON | ### 2.2 充电枪表映射 | Web 字段 (pile_connector_info) | JCPP 字段 (t_gun) | 映射说明 | |-------------------------------|------------------|---------| | id (int) | - | Web 主键,不同步 | | pile_connector_code (varchar(20)) | gun_code (varchar(255)) | 充电枪编码,唯一标识 | | name (varchar(20)) | gun_name (varchar(255)) | 充电枪名称 | | pile_sn (varchar(20)) | pile_id (uuid) | ⚠️ 需要通过 pile_code 查询 pile_id | | - | gun_no (varchar(255)) | 枪号,从 pile_connector_code 提取 | | - | station_id (uuid) | ✅ 统一使用固定值 '88bca8da-cdbf-6587-aecc-75784838c501' | ### 2.3 关键问题 #### 问题1:station_id 类型映射(int → uuid) **解决方案**: - ✅ 统一使用固定的 UUID 值:`88bca8da-cdbf-6587-aecc-75784838c501` - 所有充电桩都使用这个固定的 station_id - Web 的原始 station_id 保存在 additional_info 中便于追溯 #### 问题2:pile_id 获取 **解决方案**: - 先同步充电桩,获取返回的 pile_id - 再同步充电枪时,通过 pile_code 查询 pile_id #### 问题3:gun_no 提取 **解决方案**: - pile_connector_code 格式为 "桩号+枪号"(如:20231212000010**01**) - 提取最后 2 位作为 gun_no --- ## 三、实现方案 ### 3.1 Web 项目实现(本项目) #### 3.1.1 数据传输对象(DTO) **文件位置**:`jsowell-pile/src/main/java/com/jsowell/pile/jcpp/dto/sync/` 1. **JcppPileSyncDTO** - 充电桩同步数据 ```java { "pileCode": "20231212000010", "pileName": "1号充电桩", "protocol": "yunkuaichongV150", "brand": "特来电", "model": "AC-7KW", "manufacturer": "特来电", "type": "OPERATION", // OPERATION-运营桩, PERSONAL-个人桩 "additionalInfo": { "webPileId": 6844, "webStationId": 123, // 保存 Web 的原始 station_id "businessType": "1", "secretKey": "abc123", "longitude": "116.404", "latitude": "39.915", "iccid": "89860123456789012345" } } ``` **注意**:所有充电桩的 station_id 统一使用固定值 `88bca8da-cdbf-6587-aecc-75784838c501` 2. **JcppGunSyncDTO** - 充电枪同步数据 ```java { "gunCode": "2023121200001001", "gunName": "1号枪", "gunNo": "01", "pileCode": "20231212000010", "additionalInfo": { "webGunId": 30060, "status": "1", "parkNo": "A01" } } ``` 3. **JcppSyncRequest** - 同步请求 ```java { "syncType": "FULL", // FULL-全量, INCREMENTAL-增量 "lastSyncTime": "2025-12-30 10:00:00", // 增量同步时使用 "piles": [...], "guns": [...] } ``` 4. **JcppSyncResponse** - 同步响应 ```java { "success": true, "message": "同步成功", "totalPiles": 100, "successPiles": 98, "failedPiles": 2, "totalGuns": 200, "successGuns": 195, "failedGuns": 5, "errors": [...] } ``` #### 3.1.2 服务接口 **文件位置**:`jsowell-pile/src/main/java/com/jsowell/pile/jcpp/service/` 1. **IJcppPileSyncService** - 充电桩同步服务接口 ```java public interface IJcppPileSyncService { /** * 全量同步充电桩数据到 JCPP */ JcppSyncResponse syncAllPiles(); /** * 增量同步充电桩数据到 JCPP * @param lastSyncTime 上次同步时间 */ JcppSyncResponse syncIncrementalPiles(Date lastSyncTime); /** * 同步单个充电桩 */ boolean syncSinglePile(String pileSn); } ``` 2. **JcppPileSyncServiceImpl** - 实现类 - 查询 Web 数据库 - 转换数据格式 - 调用 JCPP 接口发送数据 - 处理同步结果 #### 3.1.3 Controller 接口 **文件位置**:`jsowell-admin/src/main/java/com/jsowell/web/controller/jcpp/` **JcppPileSyncController** ```java @RestController @RequestMapping("/jcpp/sync") public class JcppPileSyncController { /** * 全量同步充电桩数据 * POST /jcpp/sync/full */ @PostMapping("/full") public AjaxResult syncFull(); /** * 增量同步充电桩数据 * POST /jcpp/sync/incremental * @param lastSyncTime 上次同步时间(可选,默认取上次记录) */ @PostMapping("/incremental") public AjaxResult syncIncremental(@RequestParam(required = false) Date lastSyncTime); /** * 同步单个充电桩 * POST /jcpp/sync/pile/{pileSn} */ @PostMapping("/pile/{pileSn}") public AjaxResult syncSinglePile(@PathVariable String pileSn); /** * 查询同步记录 * GET /jcpp/sync/records */ @GetMapping("/records") public TableDataInfo getSyncRecords(); } ``` #### 3.1.4 同步记录表 **表名**:`jcpp_sync_record` ```sql CREATE TABLE `jcpp_sync_record` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `sync_type` varchar(20) NOT NULL COMMENT '同步类型(FULL-全量;INCREMENTAL-增量)', `sync_status` varchar(20) NOT NULL COMMENT '同步状态(RUNNING-进行中;SUCCESS-成功;FAILED-失败)', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime DEFAULT NULL COMMENT '结束时间', `total_piles` int(11) DEFAULT 0 COMMENT '总充电桩数', `success_piles` int(11) DEFAULT 0 COMMENT '成功充电桩数', `failed_piles` int(11) DEFAULT 0 COMMENT '失败充电桩数', `total_guns` int(11) DEFAULT 0 COMMENT '总充电枪数', `success_guns` int(11) DEFAULT 0 COMMENT '成功充电枪数', `failed_guns` int(11) DEFAULT 0 COMMENT '失败充电枪数', `error_message` text COMMENT '错误信息', `create_by` varchar(20) DEFAULT NULL COMMENT '创建人', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_sync_type` (`sync_type`), KEY `idx_start_time` (`start_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='JCPP 充电桩同步记录表'; ``` #### 3.1.5 配置项 **配置文件**:`application-{env}.yml` ```yaml jcpp: sync: # JCPP 同步接口地址 api-url: http://jcpp-server:8080/api/sync # 批量同步大小 batch-size: 100 # 超时时间(秒) timeout: 60 # 是否启用自动增量同步 auto-sync-enabled: false # 自动同步间隔(分钟) auto-sync-interval: 30 ``` --- ### 3.2 JCPP 项目实现(需要配合) #### 3.2.1 需要实现的接口 **接口1:接收充电桩同步数据** ``` POST /api/sync/piles Content-Type: application/json Request Body: { "piles": [ { "pileCode": "20231212000010", "pileName": "1号充电桩", "protocol": "yunkuaichongV150", "brand": "特来电", "model": "AC-7KW", "manufacturer": "特来电", "type": "OPERATION", "additionalInfo": { "webStationId": 123 // Web 的原始 station_id } } ] } Response: { "success": true, "message": "同步成功", "results": [ { "pileCode": "20231212000010", "pileId": "uuid", "success": true, "message": "创建成功" } ] } ``` **注意**:所有充电桩的 station_id 统一使用固定值 `88bca8da-cdbf-6587-aecc-75784838c501` **接口2:接收充电枪同步数据** ``` POST /api/sync/guns Content-Type: application/json Request Body: { "guns": [ { "gunCode": "2023121200001001", "gunName": "1号枪", "gunNo": "01", "pileCode": "20231212000010", "additionalInfo": {...} } ] } Response: { "success": true, "message": "同步成功", "results": [...] } ``` #### 3.2.2 数据处理逻辑 1. **充电桩同步逻辑** - 根据 pile_code 判断是否已存在 - 存在则更新,不存在则创建 - station_id 统一使用固定值 `88bca8da-cdbf-6587-aecc-75784838c501` - 返回 pile_id (uuid) 2. **充电枪同步逻辑** - 根据 gun_code 判断是否已存在 - 通过 pile_code 查询 pile_id - station_id 统一使用固定值 `88bca8da-cdbf-6587-aecc-75784838c501` - 存在则更新,不存在则创建 --- ## 四、实现步骤 ### 阶段一:Web 项目基础实现 ✅ - [x] 1. 创建 DTO 类(JcppPileSyncDTO、JcppGunSyncDTO、JcppSyncRequest、JcppSyncResponse、JcppSyncResult) - [x] 2. 创建同步记录表(jcpp_sync_record)及 Mapper - [x] 3. 创建 Service 接口和实现类(IJcppPileSyncService、JcppPileSyncServiceImpl) - [x] 4. 创建 Controller 接口(JcppPileSyncController) - [x] 5. 添加配置项(application-sit.yml) **已完成文件**: - DTO: `JcppPileSyncDTO.java`, `JcppGunSyncDTO.java`, `JcppSyncRequest.java`, `JcppSyncResponse.java`, `JcppSyncResult.java` - Domain: `JcppSyncRecord.java` - Mapper: `JcppSyncRecordMapper.java`, `JcppSyncRecordMapper.xml` - Service: `IJcppPileSyncService.java`, `JcppPileSyncServiceImpl.java` - Controller: `JcppPileSyncController.java` - SQL: `sql/jcpp_sync_record.sql` - Config: `application-sit.yml` (已添加 jcpp.sync 配置) ### 阶段二:JCPP 项目配合实现 ⏳ - [ ] 1. 实现充电桩同步接口(使用固定 station_id) - [ ] 2. 实现充电枪同步接口(使用固定 station_id) ### 阶段三:联调测试 ⏳ - [ ] 1. 测试全量同步 - [ ] 2. 测试增量同步 - [ ] 3. 测试单个充电桩同步 - [ ] 4. 测试异常场景 - [ ] 5. 性能测试 ### 阶段四:优化完善 ⏳ - [ ] 1. 添加重试机制 - [ ] 2. 添加同步进度查询 - [ ] 3. 添加定时自动同步 - [ ] 4. 完善错误处理和日志 --- ## 五、技术要点 ### 5.1 数据转换 1. **business_type 映射** - Web: "1"-运营桩, "2"-个人桩 - JCPP: "OPERATION"-运营桩, "PERSONAL"-个人桩 2. **gun_no 提取** - pile_connector_code: "2023121200001001" - gun_no: "01" (最后2位) 3. **additional_info 构建** - 将 Web 的其他字段存储为 JSON - 保留原始 ID 便于追溯 ### 5.2 性能优化 1. **批量同步** - 每批 100 条数据 - 避免一次性加载所有数据 2. **异步处理** - 全量同步使用异步任务 - 返回任务 ID,可查询进度 3. **增量同步** - 基于 update_time 字段 - 记录上次同步时间 ### 5.3 异常处理 1. **网络异常** - 重试机制(最多3次) - 指数退避策略 2. **数据异常** - 记录失败数据 - 继续处理其他数据 3. **事务处理** - JCPP 端保证事务一致性 - Web 端记录同步状态 --- ## 六、注意事项 1. **数据一致性** - 充电桩必须先于充电枪同步 - 确保 pile_code 唯一性 2. **性能考虑** - 全量同步可能耗时较长 - 建议在业务低峰期执行 3. **安全性** - 同步接口需要鉴权 - 敏感数据加密传输 4. **监控告警** - 同步失败告警 - 同步耗时监控 --- ## 七、变更记录 | 日期 | 版本 | 修改人 | 修改内容 | |------|------|--------|----------| | 2025-12-30 | v1.0 | Claude | 创建文档,制定实现计划 | --- ## 八、相关文档 - [充电桩数据同步需求.md](./充电桩数据同步需求.md) - [JCPP对接进度文档.md](./JCPP对接进度文档.md)