# 开发者指南

<cite>
**本文档中引用的文件**  
- [README.md](file://README.md)
- [pom.xml](file://pom.xml)
- [docker/start.sh](file://docker/start.sh)
- [docker/docker-compose.monolith.yml](file://docker/docker-compose.monolith.yml)
- [jcpp-app-bootstrap/src/main/resources/app-service.yml](file://jcpp-app-bootstrap/src/main/resources/app-service.yml)
- [jcpp-protocol-bootstrap/src/main/resources/protocol-service.yml](file://jcpp-protocol-bootstrap/src/main/resources/protocol-service.yml)
- [jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java](file://jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java)
- [jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java](file://jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java)
- [jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/YunkuaichongV150ProtocolBootstrap.java](file://jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/YunkuaichongV150ProtocolBootstrap.java)
- [jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java)
- [jcpp-web-ui/package.json](file://jcpp-web-ui/package.json)
</cite>

## 目录

1. [环境搭建](#环境搭建)
2. [代码获取与构建](#代码获取与构建)
3. [本地运行](#本地运行)
4. [开发新协议](#开发新协议)
5. [调试技巧](#调试技巧)

## 环境搭建

在开始开发之前，需要安装以下必要的开发工具：

1. **JDK 21**：本项目基于Java 21开发，需安装JDK 21并配置JAVA_HOME环境变量。
2. **Maven**：用于构建Java后端模块，建议使用最新稳定版本。
3. **Node.js**：用于构建前端项目，建议使用LTS版本（如v18或v20）。
4. **Docker**：用于启动依赖服务（PostgreSQL, Redis, Kafka等），建议安装最新稳定版。

安装完成后，可通过以下命令验证：

```bash
java -version
mvn -version
node --version
docker --version
```

**Section sources**

- [pom.xml](file://pom.xml#L15-L20)
- [jcpp-web-ui/package.json](file://jcpp-web-ui/package.json#L1-L10)

## 代码获取与构建

### 代码获取

使用Git克隆项目仓库：

```bash
git clone https://github.com/sanbing-java/JChargePointProtocol.git
cd JChargePointProtocol
```

### 后端构建

项目包含多个Maven模块，主要后端模块包括`jcpp-app`和`jcpp-protocol-*`系列模块。

构建所有模块：

```bash
mvn clean install -DskipTests
```

仅构建特定模块（如`jcpp-app`）：

```bash
cd jcpp-app
mvn clean package -DskipTests
```

### 前端构建

前端项目位于`jcpp-web-ui`目录，使用npm进行构建。

进入前端目录并安装依赖：

```bash
cd jcpp-web-ui
npm install
```

构建生产版本：

```bash
npm run build
```

启动开发服务器：

```bash
npm start
```

**Section sources**

- [pom.xml](file://pom.xml#L100-L120)
- [jcpp-web-ui/package.json](file://jcpp-web-ui/package.json#L10-L20)

## 本地运行

### 启动依赖服务

项目依赖PostgreSQL、Redis和Kafka等服务，可通过Docker Compose一键启动。

使用提供的启动脚本：

```bash
bash docker/start.sh
```

或手动执行Docker Compose命令：

```bash
docker-compose -f docker/docker-compose.postgres.yml -f docker/docker-compose.redis-standalone.yml -f docker/docker-compose.kafka.yml up -d
```

### 启动应用服务

项目包含两个核心启动模块：`jcpp-app-bootstrap`（应用后端）和`jcpp-protocol-bootstrap`（协议前置）。

1. 启动应用后端服务：

```bash
cd jcpp-app-bootstrap
mvn spring-boot:run
```

2. 启动协议前置服务：

```bash
cd jcpp-protocol-bootstrap
mvn spring-boot:run
```

服务启动后，可通过以下地址访问：

- 应用后端API：http://localhost:8080
- 协议服务gRPC端口：9090
- 管理后台：http://localhost:8080/page/dashboard

```mermaid
graph TD
A[Docker Compose] --> B[PostgreSQL]
A --> C[Redis]
A --> D[Kafka]
E[jcpp-app-bootstrap] --> B
E --> C
F[jcpp-protocol-bootstrap] --> D
F --> C
E --> G[前端UI]
F --> E
```

**Diagram sources**

- [docker/docker-compose.monolith.yml](file://docker/docker-compose.monolith.yml#L1-L20)
- [jcpp-app-bootstrap/src/main/resources/app-service.yml](file://jcpp-app-bootstrap/src/main/resources/app-service.yml#L1-L50)
- [jcpp-protocol-bootstrap/src/main/resources/protocol-service.yml](file://jcpp-protocol-bootstrap/src/main/resources/protocol-service.yml#L1-L50)

**Section sources**

- [docker/start.sh](file://docker/start.sh#L1-L20)
- [jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java](file://jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java#L1-L20)
- [jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java](file://jcpp-protocol-bootstrap/src/main/java/sanbing/jcpp/protocol/JCPPProtocolServiceApplication.java#L1-L20)

## 开发新协议

以实现一个新的充电桩协议为例，说明开发流程。

### 继承ProtocolBootstrap

创建新的协议启动类，继承`ProtocolBootstrap`抽象类。参考现有协议实现，如`YunkuaichongV150ProtocolBootstrap`。

```java
@ProtocolComponent("NEW_PROTOCOL_V100")
public class NewProtocolV100Bootstrap extends ProtocolBootstrap {
    
    @Override
    protected String getProtocolName() {
        return "NEW_PROTOCOL_V100";
    }
    
    @Override
    protected void _init() {
        // 初始化逻辑
    }
    
    @Override
    protected void _destroy() {
        // 销毁逻辑
    }
    
    @Override
    protected ProtocolMessageProcessor messageProcessor() {
        return new NewProtocolMessageProcessor(forwarder, protocolContext);
    }
}
```

### 实现消息处理器

创建消息处理器类，继承`ProtocolMessageProcessor`，实现上行和下行消息处理逻辑。

```java
public class NewProtocolMessageProcessor extends ProtocolMessageProcessor {
    
    public NewProtocolMessageProcessor(Forwarder forwarder, ProtocolContext protocolContext) {
        super(forwarder, protocolContext);
    }
    
    @Override
    protected void uplinkHandle(ListenerToHandlerMsg listenerToHandlerMsg) {
        // 处理上行消息
    }
    
    @Override
    protected void doDownlinkHandle(SessionToHandlerMsg sessionToHandlerMsg) {
        // 处理下行消息
    }
}
```

### 定义命令类

根据协议规范定义上行和下行命令类，通常包含消息头、消息体、校验等字段。

### 配置文件注册

在`protocol-service.yml`中注册新协议的配置，包括监听端口、转发方式等。

```yaml
service:
  protocols:
    newProtocolV100:
      enabled: true
      listener:
        tcp:
          bind-port: 38021
      forwarder:
        type: kafka
```

```mermaid
classDiagram
class ProtocolBootstrap {
+init()
+destroy()
+health()
+getProtocolName()
+_init()
+_destroy()
+messageProcessor()
}
class NewProtocolV100Bootstrap {
+getProtocolName()
+_init()
+_destroy()
+messageProcessor()
}
class ProtocolMessageProcessor {
+uplinkHandleAsync()
+downlinkHandle()
+uplinkHandle()
+doDownlinkHandle()
}
class NewProtocolMessageProcessor {
+uplinkHandle()
+doDownlinkHandle()
}
ProtocolBootstrap <|-- NewProtocolV100Bootstrap
ProtocolMessageProcessor <|-- NewProtocolMessageProcessor
NewProtocolV100Bootstrap --> NewProtocolMessageProcessor : "creates"
```

**Diagram sources**

- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L1-L50)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L1-L30)
- [jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/YunkuaichongV150ProtocolBootstrap.java](file://jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/YunkuaichongV150ProtocolBootstrap.java#L1-L20)

**Section sources**

- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L1-L127)
- [jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L1-L78)
- [jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/YunkuaichongV150ProtocolBootstrap.java](file://jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/YunkuaichongV150ProtocolBootstrap.java#L1-L48)
- [jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L1-L48)

## 调试技巧

### 查看日志

应用日志默认输出到控制台，并保存在`logs/`目录下。关键日志文件包括：

- `logs/accesslog/`：HTTP访问日志
- `logs/gc/gc.log`：JVM GC日志
- `logs/heapdump/`：内存溢出时的堆转储文件

可通过配置`app-service.yml`调整日志级别：

```yaml
logging:
  level:
    sanbing: DEBUG
```

### 远程调试

通过JVM参数启用远程调试，修改启动脚本`docker/start.sh`：

```bash
export JAVA_OPTS_EXTEND="-Xdebug -Xrunjdwp:transport=dt_socket,address=0.0.0.0:8000,server=y,suspend=n"
```

在IDE中配置远程调试连接：

- 主机：localhost
- 端口：8000
- 调试器：Java

### RPC调用调试

通过`RpcController`提供的API接口发送调试指令：

```bash
curl -X POST http://localhost:8080/api/rpc/oneway \
  -H "Content-Type: application/json" \
  -d '{
    "method": "startCharge",
    "parameter": {"pileCode": "P123", "gunNo": "1"}
  }'
```

```mermaid
sequenceDiagram
participant Dev as 开发者
participant IDE as IDE
participant App as jcpp-app-bootstrap
participant Protocol as jcpp-protocol-bootstrap
Dev->>IDE : 配置远程调试
IDE->>App : 连接调试端口8000
Dev->>App : 发送RPC指令
App->>Protocol : 通过Kafka转发
Protocol->>App : 处理协议消息
App-->>Dev : 返回响应结果
```

**Diagram sources**

- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java#L1-L70)
- [docker/start.sh](file://docker/start.sh#L15-L18)
- [jcpp-app-bootstrap/src/main/resources/app-service.yml](file://jcpp-app-bootstrap/src/main/resources/app-service.yml#L1-L10)

**Section sources**

- [docker/start.sh](file://docker/start.sh#L15-L18)
- [jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java#L30-L150)
- [jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java#L1-L1000)