寻车铃命令发送

This commit is contained in:
attiya 2025-10-30 16:38:04 +08:00
parent 7a87016761
commit 8da950c803
8 changed files with 123 additions and 21 deletions

View File

@ -1,7 +1,11 @@
package org.cdzy.gather.kafka; package org.cdzy.gather.kafka;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.netty.handler.codec.mqtt.MqttQoS;
import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.cdzy.gather.mqtt.MqttPoolClient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.KafkaListener;
@ -17,6 +21,8 @@ public class KafkaConsumer {
private static final Logger log= LoggerFactory.getLogger(KafkaConsumer.class); private static final Logger log= LoggerFactory.getLogger(KafkaConsumer.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
/** /**
* 消费者监听消息 * 消费者监听消息
* *
@ -25,8 +31,10 @@ public class KafkaConsumer {
@KafkaListener(topics = {"command"}) @KafkaListener(topics = {"command"})
public void onMessage(ConsumerRecord<?, ?> record) throws JsonProcessingException { public void onMessage(ConsumerRecord<?, ?> record) throws JsonProcessingException {
log.info("[KAFKA接收] 主题: {}, 内容: {}", record.topic(), record.value()); log.info("[KAFKA接收] 主题: {}, 内容: {}", record.topic(), record.value());
// ObjectMapper objectMapper = new ObjectMapper(); String jsonStr = String.valueOf(record.value());
// CMDMsg cmdMsg = objectMapper.readValue(String.valueOf(record.value()), CMDMsg.class); ObjectNode objectNode = objectMapper.readValue(jsonStr, ObjectNode.class);
// MqttPoolClient.sendMessage(cmdMsg.getPrefix()+"/"+cmdMsg.getGroup()+"/"+cmdMsg.getDeviceId(), MqttQoS.valueOf(cmdMsg.getQos()), cmdMsg.getCommand()); String topic = objectNode.get("topic").asText();
String command = objectNode.get("command").asText();
MqttPoolClient.sendMessage(topic, MqttQoS.AT_LEAST_ONCE, command);
} }
} }

View File

@ -1,7 +1,6 @@
package org.cdzy.gather.mqtt; package org.cdzy.gather.mqtt;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import io.netty.channel.Channel; import io.netty.channel.Channel;
@ -157,7 +156,7 @@ public class MqttHandler extends SimpleChannelInboundHandler<MqttMessage> {
* *
* @param publishMsg 信息 * @param publishMsg 信息
*/ */
private void handlePublish(MqttPublishMessage publishMsg) throws JsonProcessingException { private void handlePublish(MqttPublishMessage publishMsg) {
// 处理PUBLISH消息含Payload // 处理PUBLISH消息含Payload
String topic = publishMsg.variableHeader().topicName(); String topic = publishMsg.variableHeader().topicName();
List<String> list = Arrays.stream(topic.split("/")).toList(); List<String> list = Arrays.stream(topic.split("/")).toList();
@ -171,14 +170,18 @@ public class MqttHandler extends SimpleChannelInboundHandler<MqttMessage> {
} }
KafkaProducer kafkaProducer = SpringContextHolder.getBean(KafkaProducer.class); KafkaProducer kafkaProducer = SpringContextHolder.getBean(KafkaProducer.class);
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
ObjectNode objectNode = objectMapper.readValue(payload, ObjectNode.class); try {
objectNode.put("deviceId", list.get(list.size() - 1)); ObjectNode objectNode = objectMapper.readValue(payload, ObjectNode.class);
objectNode.put("r_topic", list.get(1)); objectNode.put("deviceId", list.get(list.size() - 1));
if (topic.contains("rsp")){ objectNode.put("r_topic", list.get(1));
kafkaProducer.send("msg_rsp", objectNode.textValue()); if (topic.contains("rsp")){
}else if (topic.contains("rpt")){ kafkaProducer.send("msg_rsp", objectNode.toString());
kafkaProducer.send("msg_rpt", objectNode.textValue()); }else if (topic.contains("rpt")){
} kafkaProducer.send("msg_rpt", objectNode.toString());
}
}catch (JsonProcessingException e){
log.error(e.getMessage());
}
} }
private void handleSubAck(MqttSubAckMessage subAck) { private void handleSubAck(MqttSubAckMessage subAck) {

View File

@ -1,6 +1,5 @@
package com.cdzy.operations.controller; package com.cdzy.operations.controller;
import com.cdzy.common.ex.EbikeException;
import com.cdzy.common.model.request.PageParam; import com.cdzy.common.model.request.PageParam;
import com.cdzy.common.model.response.JsonResult; import com.cdzy.common.model.response.JsonResult;
import com.cdzy.operations.model.dto.EbikeEcuInOverview; import com.cdzy.operations.model.dto.EbikeEcuInOverview;
@ -8,19 +7,14 @@ import com.cdzy.operations.model.entity.EbikeEcuInfo;
import com.cdzy.operations.model.vo.EbikeEcuInfoBatchVo; import com.cdzy.operations.model.vo.EbikeEcuInfoBatchVo;
import com.cdzy.operations.model.vo.EbikeEcuInfoVo; import com.cdzy.operations.model.vo.EbikeEcuInfoVo;
import com.cdzy.operations.service.EbikeEcuInfoService; import com.cdzy.operations.service.EbikeEcuInfoService;
import com.cdzy.operations.utils.EmqxApiClient;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import static com.cdzy.operations.model.entity.table.EbikeEcuInfoTableDef.EBIKE_ECU_INFO;
/** /**
* 中控基本信息 控制层 * 中控基本信息 控制层
* *
@ -132,6 +126,18 @@ public class EbikeEcuInfoController {
} }
/**
* 校验SN或BikeCode
*
* @return 执行结构
*/
@GetMapping("checkSnOrBikeCode")
public JsonResult<?> checkSnOrBikeCode(String ecuSn,String bikeCode) throws IOException {
boolean result = ebikeEcuInfoService.checkSnOrBikeCode(ecuSn,bikeCode);
return JsonResult.success(result);
}
/** /**
* 设备是否在线 * 设备是否在线
* *

View File

@ -0,0 +1,9 @@
package com.cdzy.operations.enums;
/**
* @author attiya
* @since 2025-10-30
*/
public interface CommandType {
String FIND_BIKE = "FIND_BIKE";
}

View File

@ -50,4 +50,12 @@ public interface EbikeEcuInfoService extends IService<EbikeEcuInfo> {
* @return 结果 * @return 结果
*/ */
boolean findBike(String ecuSn, String bikeCode); boolean findBike(String ecuSn, String bikeCode);
/**
* 校验参数
* @param ecuSn 中控SN码
* @param bikeCode 车辆编号
* @return 结果
*/
boolean checkSnOrBikeCode(String ecuSn, String bikeCode);
} }

View File

@ -2,9 +2,12 @@ package com.cdzy.operations.service.impl;
import com.cdzy.common.ex.EbikeException; import com.cdzy.common.ex.EbikeException;
import com.cdzy.operations.component.KafkaProducer; import com.cdzy.operations.component.KafkaProducer;
import com.cdzy.operations.enums.CommandType;
import com.cdzy.operations.enums.EcuBrand; import com.cdzy.operations.enums.EcuBrand;
import com.cdzy.operations.model.entity.EbikeEcuInfo; import com.cdzy.operations.model.entity.EbikeEcuInfo;
import com.cdzy.operations.service.CommandService; import com.cdzy.operations.service.CommandService;
import com.cdzy.operations.utils.CommandUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -22,6 +25,8 @@ import java.util.concurrent.*;
@Service @Service
public class CommandServiceImpl implements CommandService { public class CommandServiceImpl implements CommandService {
private final String topic = "command";
private final ExecutorService executor = Executors.newFixedThreadPool(10); private final ExecutorService executor = Executors.newFixedThreadPool(10);
private final ConcurrentHashMap<String, CompletableFuture<Boolean>> pendingRequests = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, CompletableFuture<Boolean>> pendingRequests = new ConcurrentHashMap<>();
@ -32,9 +37,19 @@ public class CommandServiceImpl implements CommandService {
@Override @Override
public boolean findBike(EbikeEcuInfo ebikeEcuInfo) { public boolean findBike(EbikeEcuInfo ebikeEcuInfo) {
boolean result = false; boolean result = false;
String taskId = createTaskId();
switch (ebikeEcuInfo.getEcuBrand()){ switch (ebikeEcuInfo.getEcuBrand()){
case EcuBrand.GUANG_HE_TONG -> result = submitTaskAndWait("command",createTaskId(),"测试"); case EcuBrand.GUANG_HE_TONG:
default -> throw new EbikeException("该品牌中控暂未接入"); String command = null;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(),taskId, CommandType.FIND_BIKE);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
result = submitTaskAndWait(topic, taskId,command);
break;
default :
throw new EbikeException("该品牌中控暂未接入");
} }
return result; return result;
} }

View File

@ -132,6 +132,22 @@ public class EbikeEcuInfoServiceImpl extends ServiceImpl<EbikeEcuInfoMapper, Ebi
} }
} }
@Override
public boolean checkSnOrBikeCode(String ecuSn, String bikeCode) {
try {
check(ecuSn, bikeCode);
if (StringUtil.hasText(ecuSn)) {
checkEcuSn(ecuSn);
return true;
} else {
getEcu(bikeCode);
return true;
}
} catch (Exception e) {
return false;
}
}
private EbikeEcuInfo checkEcuSn(String ecuSn) { private EbikeEcuInfo checkEcuSn(String ecuSn) {
QueryWrapper queryWrapper = QueryWrapper.create() QueryWrapper queryWrapper = QueryWrapper.create()
.where(EBIKE_ECU_INFO.ECU_SN.eq(ecuSn)); .where(EBIKE_ECU_INFO.ECU_SN.eq(ecuSn));

View File

@ -0,0 +1,37 @@
package com.cdzy.operations.utils;
import com.cdzy.common.ex.EbikeException;
import com.cdzy.operations.enums.CommandType;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author attiya
* @since 2025-10-30
*/
public class CommandUtil {
private static final ObjectMapper mapper = new ObjectMapper();
private static final String prefix = "ecu/rsp/cdzybms/";
public static String guang_he_tong(String ecuSn, String taskId, String code) throws JsonProcessingException {
String topic = prefix + ecuSn;
ObjectNode jsonNode = mapper.createObjectNode();
jsonNode.put("topic", topic);
switch (code) {
case CommandType.FIND_BIKE:
String json = "{\"c\":14,\"tid\":\"e8957e7dde5a487895b22286d5046ffc\",\"param\":{\"volume\":50,\"idx\":5}}";
ObjectNode objectNode = mapper.readValue(json,ObjectNode.class);
objectNode.put("tid",taskId);
jsonNode.put("command",objectNode.toString());
break;
default :
throw new EbikeException("该命令暂未接入");
}
return jsonNode.toString();
}
}