Files
jsowell-charger-web/doc/充电桩数据同步实现计划.md
2025-12-30 15:59:34 +08:00

12 KiB
Raw Blame History

充电桩数据同步实现计划

创建时间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 关键问题

问题1station_id 类型映射int → uuid

解决方案

  • 统一使用固定的 UUID 值:88bca8da-cdbf-6587-aecc-75784838c501
  • 所有充电桩都使用这个固定的 station_id
  • Web 的原始 station_id 保存在 additional_info 中便于追溯

问题2pile_id 获取

解决方案

  • 先同步充电桩,获取返回的 pile_id
  • 再同步充电枪时,通过 pile_code 查询 pile_id

问题3gun_no 提取

解决方案

  • pile_connector_code 格式为 "桩号+枪号"2023121200001001
  • 提取最后 2 位作为 gun_no

三、实现方案

3.1 Web 项目实现(本项目)

3.1.1 数据传输对象DTO

文件位置jsowell-pile/src/main/java/com/jsowell/pile/jcpp/dto/sync/

  1. JcppPileSyncDTO - 充电桩同步数据
{
    "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

  1. JcppGunSyncDTO - 充电枪同步数据
{
    "gunCode": "2023121200001001",
    "gunName": "1号枪",
    "gunNo": "01",
    "pileCode": "20231212000010",
    "additionalInfo": {
        "webGunId": 30060,
        "status": "1",
        "parkNo": "A01"
    }
}
  1. JcppSyncRequest - 同步请求
{
    "syncType": "FULL",  // FULL-全量, INCREMENTAL-增量
    "lastSyncTime": "2025-12-30 10:00:00",  // 增量同步时使用
    "piles": [...],
    "guns": [...]
}
  1. JcppSyncResponse - 同步响应
{
    "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 - 充电桩同步服务接口
public interface IJcppPileSyncService {
    /**
     * 全量同步充电桩数据到 JCPP
     */
    JcppSyncResponse syncAllPiles();

    /**
     * 增量同步充电桩数据到 JCPP
     * @param lastSyncTime 上次同步时间
     */
    JcppSyncResponse syncIncrementalPiles(Date lastSyncTime);

    /**
     * 同步单个充电桩
     */
    boolean syncSinglePile(String pileSn);
}
  1. JcppPileSyncServiceImpl - 实现类
  • 查询 Web 数据库
  • 转换数据格式
  • 调用 JCPP 接口发送数据
  • 处理同步结果

3.1.3 Controller 接口

文件位置jsowell-admin/src/main/java/com/jsowell/web/controller/jcpp/

JcppPileSyncController

@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

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

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 项目基础实现

  • 1. 创建 DTO 类JcppPileSyncDTO、JcppGunSyncDTO、JcppSyncRequest、JcppSyncResponse、JcppSyncResult
  • 2. 创建同步记录表jcpp_sync_record及 Mapper
  • 3. 创建 Service 接口和实现类IJcppPileSyncService、JcppPileSyncServiceImpl
  • 4. 创建 Controller 接口JcppPileSyncController
  • 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 创建文档,制定实现计划

八、相关文档