对接jcpp

This commit is contained in:
Guoqs
2025-12-27 15:05:41 +08:00
parent bc3e8091de
commit 7d170dbe64
35 changed files with 5185 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
package com.jsowell.web.controller.jcpp;
import com.jsowell.common.core.controller.BaseController;
import com.jsowell.common.core.domain.AjaxResult;
import com.jsowell.pile.domain.PileBasicInfo;
import com.jsowell.pile.domain.PileBillingTemplate;
import com.jsowell.pile.jcpp.dto.JcppPricingModel;
import com.jsowell.pile.jcpp.util.PricingModelConverter;
import com.jsowell.pile.service.PileBasicInfoService;
import com.jsowell.pile.service.PileBillingTemplateService;
import com.jsowell.pile.vo.web.BillingTemplateVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* JCPP 计费模板接口
*
* @author jsowell
*/
// @Slf4j
@Api(tags = "JCPP计费模板接口")
@RestController
@RequestMapping("/api/jcpp")
public class JcppBillingController extends BaseController {
@Autowired
private PileBasicInfoService pileBasicInfoService;
@Autowired
private PileBillingTemplateService pileBillingTemplateService;
/**
* 获取充电桩计费模板
*
* @param pileCode 充电桩编码
* @return 计费模板
*/
@ApiOperation("获取充电桩计费模板")
@GetMapping("/billing/{pileCode}")
public AjaxResult getBillingTemplate(
@ApiParam(value = "充电桩编码", required = true) @PathVariable String pileCode) {
try {
logger.info("查询充电桩计费模板: pileCode={}", pileCode);
// 1. 根据 pileCode 查询充电桩
PileBasicInfo pileInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileCode);
if (pileInfo == null) {
logger.warn("充电桩不存在: pileCode={}", pileCode);
return AjaxResult.error(404, "充电桩不存在");
}
// 2. 获取关联的计费模板 ID
BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileCode);
if (billingTemplateVO == null || billingTemplateVO.getTemplateId() == null) {
logger.warn("充电桩未配置计费模板: pileCode={}", pileCode);
return AjaxResult.error(404, "未配置计费模板");
}
Long billingTemplateId = Long.parseLong(billingTemplateVO.getTemplateId());
// 3. 查询计费模板
PileBillingTemplate template = pileBillingTemplateService.selectPileBillingTemplateById(billingTemplateId);
if (template == null) {
logger.warn("计费模板不存在: pileCode={}, billingTemplateId={}", pileCode, billingTemplateId);
return AjaxResult.error(404, "计费模板不存在");
}
// 4. 转换为 JCPP 格式
JcppPricingModel pricingModel = PricingModelConverter.convert(template);
// 5. 构建返回结果
Map<String, Object> data = new HashMap<>();
data.put("pricingId", billingTemplateId);
data.put("pricingModel", pricingModel);
logger.info("查询计费模板成功: pileCode={}, pricingId={}", pileCode, billingTemplateId);
return AjaxResult.success(data);
} catch (Exception e) {
logger.error("查询计费模板异常: pileCode={}", pileCode, e);
return AjaxResult.error("查询计费模板失败: " + e.getMessage());
}
}
/**
* 根据计费模板ID获取计费模板
*
* @param pricingId 计费模板ID
* @return 计费模板
*/
@ApiOperation("根据ID获取计费模板")
@GetMapping("/billing/id/{pricingId}")
public AjaxResult getBillingTemplateById(
@ApiParam(value = "计费模板ID", required = true) @PathVariable Long pricingId) {
try {
logger.info("查询计费模板: pricingId={}", pricingId);
// 查询计费模板
PileBillingTemplate template = pileBillingTemplateService.selectPileBillingTemplateById(pricingId);
if (template == null) {
logger.warn("计费模板不存在: pricingId={}", pricingId);
return AjaxResult.error(404, "计费模板不存在");
}
// 转换为 JCPP 格式
JcppPricingModel pricingModel = PricingModelConverter.convert(template);
// 构建返回结果
Map<String, Object> data = new HashMap<>();
data.put("pricingId", pricingId);
data.put("pricingModel", pricingModel);
logger.info("查询计费模板成功: pricingId={}", pricingId);
return AjaxResult.success(data);
} catch (Exception e) {
logger.error("查询计费模板异常: pricingId={}", pricingId, e);
return AjaxResult.error("查询计费模板失败: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,61 @@
package com.jsowell.web.controller.jcpp;
import com.jsowell.common.core.controller.BaseController;
import com.jsowell.pile.jcpp.config.JcppConfig;
import com.jsowell.pile.jcpp.dto.JcppUplinkMessage;
import com.jsowell.pile.jcpp.dto.JcppUplinkResponse;
import com.jsowell.pile.jcpp.service.IJcppMessageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* JCPP 消息接收 Controller
* 用于接收 JCPP 项目推送的充电桩上行消息
*
* @author jsowell
*/
// @Slf4j
@Api(tags = "JCPP消息接收接口")
@RestController
@RequestMapping("/api/jcpp")
public class JcppMessageController extends BaseController {
@Autowired
private IJcppMessageService jcppMessageService;
@Autowired
private JcppConfig jcppConfig;
/**
* 接收 JCPP 上行消息
*
* @param message 上行消息
* @return 响应
*/
@ApiOperation("接收JCPP上行消息")
@PostMapping("/uplink")
public JcppUplinkResponse receiveUplink(@RequestBody JcppUplinkMessage message) {
// 检查是否启用 JCPP 对接
if (!jcppConfig.isEnabled()) {
logger.warn("JCPP 对接未启用,忽略消息: {}", message.getMessageId());
return JcppUplinkResponse.error(message.getMessageId(), "JCPP 对接未启用");
}
logger.info("收到 JCPP 上行消息: messageId={}, messageType={}, pileCode={}, sessionId={}",
message.getMessageId(), message.getMessageType(),
message.getPileCode(), message.getSessionId());
try {
return jcppMessageService.handleMessage(message);
} catch (Exception e) {
logger.error("处理 JCPP 上行消息异常: messageId={}, error={}",
message.getMessageId(), e.getMessage(), e);
return JcppUplinkResponse.error(message.getMessageId(), "处理消息异常: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,85 @@
package com.jsowell.web.controller.jcpp;
import com.jsowell.common.core.controller.BaseController;
import com.jsowell.common.core.domain.AjaxResult;
import com.jsowell.pile.jcpp.service.IJcppRemoteChargeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
// import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* JCPP 远程充电 Controller
* 用于 APP/小程序发起的远程启动/停止充电
*
* @author jsowell
*/
// @Slf4j
@Api(tags = "JCPP远程充电接口")
@RestController
@RequestMapping("/api/jcpp/charge")
public class JcppRemoteChargeController extends BaseController {
@Autowired
private IJcppRemoteChargeService jcppRemoteChargeService;
/**
* 远程启动充电
*/
@ApiOperation("远程启动充电")
@PostMapping("/start")
public AjaxResult startCharging(
@ApiParam(value = "会员ID", required = true) @RequestParam String memberId,
@ApiParam(value = "充电桩编码", required = true) @RequestParam String pileCode,
@ApiParam(value = "枪编号", required = true) @RequestParam String gunNo,
@ApiParam(value = "预付金额(元)", required = true) @RequestParam String payAmount) {
try {
String orderCode = jcppRemoteChargeService.remoteStartCharging(memberId, pileCode, gunNo, payAmount);
return AjaxResult.success("启动指令已发送", orderCode);
} catch (Exception e) {
logger.error("远程启动充电失败, memberId: {}, pileCode: {}, error: {}",
memberId, pileCode, e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
}
/**
* 远程停止充电
*/
@ApiOperation("远程停止充电")
@PostMapping("/stop")
public AjaxResult stopCharging(
@ApiParam(value = "会员ID", required = true) @RequestParam String memberId,
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
try {
boolean result = jcppRemoteChargeService.remoteStopCharging(memberId, orderCode);
if (result) {
return AjaxResult.success("停止指令已发送");
} else {
return AjaxResult.error("停止充电失败");
}
} catch (Exception e) {
logger.error("远程停止充电失败, memberId: {}, orderCode: {}, error: {}",
memberId, orderCode, e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
}
/**
* 检查充电桩是否在线
*/
@ApiOperation("检查充电桩是否在线")
@GetMapping("/online/{pileCode}")
public AjaxResult checkOnline(
@ApiParam(value = "充电桩编码", required = true) @PathVariable String pileCode) {
try {
boolean online = jcppRemoteChargeService.isPileOnline(pileCode);
return AjaxResult.success(online);
} catch (Exception e) {
logger.error("检查充电桩在线状态失败, pileCode: {}, error: {}", pileCode, e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
}
}