diff --git a/admin/src/main/java/com/multictrl/modules/business/handler/TopicDistributor.java b/admin/src/main/java/com/multictrl/modules/business/handler/TopicDistributor.java index 82119f2..e749afb 100644 --- a/admin/src/main/java/com/multictrl/modules/business/handler/TopicDistributor.java +++ b/admin/src/main/java/com/multictrl/modules/business/handler/TopicDistributor.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil; import com.multictrl.common.constant.BusinessConstant; import com.multictrl.modules.business.q20.handler.Q20EventsHandler; import com.multictrl.modules.business.q20.handler.Q20OsdTopicHandler; +import com.multictrl.modules.business.q20.handler.Q20RequestsHandler; import com.multictrl.modules.business.q20.handler.Q20StateTopicHandler; import com.multictrl.modules.business.q20.handler.Q20StatusHandler; import jakarta.annotation.PostConstruct; @@ -35,6 +36,7 @@ public class TopicDistributor { private final Q20EventsHandler q20EventsHandler; private final Q20StateTopicHandler q20StateTopicHandler; private final Q20StatusHandler q20StatusHandler; + private final Q20RequestsHandler q20RequestsHandler; private final Map handlerMap = new ConcurrentHashMap<>(); private final Map q20HandlerMap = new ConcurrentHashMap<>(); @@ -56,6 +58,7 @@ public class TopicDistributor { q20HandlerMap.put(BusinessConstant.STATE, q20StateTopicHandler); q20HandlerMap.put(BusinessConstant.STATUS, q20StatusHandler); q20HandlerMap.put(BusinessConstant.SERVICES_REPLY, servicesReplyHandler); + q20HandlerMap.put(BusinessConstant.REQUESTS, q20RequestsHandler); } public void route(String topic, String payload) { diff --git a/admin/src/main/java/com/multictrl/modules/business/q20/handler/Q20Constant.java b/admin/src/main/java/com/multictrl/modules/business/q20/handler/Q20Constant.java index a94f4a5..8bd360b 100644 --- a/admin/src/main/java/com/multictrl/modules/business/q20/handler/Q20Constant.java +++ b/admin/src/main/java/com/multictrl/modules/business/q20/handler/Q20Constant.java @@ -32,6 +32,8 @@ public interface Q20Constant { String METHOD_ROUTE_EXECUTE = "route_execute"; String METHOD_ROUTE_AUTO = "route_auto"; String METHOD_OTA = "ota"; + // Q20 requests topic method字段值(thing/device/{sn}/requests) + String METHOD_HANGAR_CHARGE_CONTROL = "hangar_charge_control"; // Q20 缓存key前缀 String Q20_OSD = "q20_osd_"; diff --git a/admin/src/main/java/com/multictrl/modules/business/q20/handler/Q20RequestsHandler.java b/admin/src/main/java/com/multictrl/modules/business/q20/handler/Q20RequestsHandler.java new file mode 100644 index 0000000..f674584 --- /dev/null +++ b/admin/src/main/java/com/multictrl/modules/business/q20/handler/Q20RequestsHandler.java @@ -0,0 +1,71 @@ +package com.multictrl.modules.business.q20.handler; + +import cn.hutool.json.JSONObject; +import com.multictrl.common.constant.BusinessConstant; +import com.multictrl.common.utils.JsonUtils; +import com.multictrl.modules.business.handler.MessageHandler; +import com.multictrl.modules.business.service.MqttPushService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * Q20设备请求消息处理(topic: thing/device/{device_sn}/requests) + *

method: hangar_charge_control(飞行器请求充电电压电流)。 + * 收到飞行器充电请求后,平台充电器自动回复 requests_reply 主题, + * 回传充电器实际可提供的电压/电流(当前按请求值原样应答,表示同意按需供电)。 + * + * @author 938693313@qq.com + * @since 1.0.0 2026/6/12 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class Q20RequestsHandler implements MessageHandler { + + private final MqttPushService mqttPushService; + + @Override + public void handleMessage(String topic, String payload, String gateway) { + JSONObject message = JsonUtils.parseObject(payload, JSONObject.class); + if (message == null) { + log.debug("Q20 requests --> payload解析失败,解析后为null"); + return; + } + + String method = message.getStr(BusinessConstant.METHOD); + if (method == null) { + log.debug("Q20 requests --> method字段缺失, topic: {}", topic); + return; + } + + if (Q20Constant.METHOD_HANGAR_CHARGE_CONTROL.equals(method)) { + handleHangarChargeControl(topic, message); + } else { + log.debug("Q20 requests --> 未知method: {}, gateway: {}", method, gateway); + } + } + + /** + * 飞行器请求充电:自动回复充电器电压/电流。 + *

请求 data: {voltage(请求充电电压V*10), current(请求充电电流A*10)}; + * 回复主题 thing/device/{sn}/requests_reply,data 回传充电器电压/电流(原样应答请求值)。 + */ + private void handleHangarChargeControl(String topic, JSONObject message) { + JSONObject data = message.getJSONObject(BusinessConstant.DATA); + int voltage = data != null ? data.getInt("voltage", 0) : 0; + int current = data != null ? data.getInt("current", 0) : 0; + + // 原样应答 tid/bid/method/gateway,data 回传充电器电压/电流,刷新时间戳 + JSONObject reply = new JSONObject(); + reply.set("voltage", voltage); + reply.set("current", current); + message.set(BusinessConstant.DATA, reply); + message.set("timestamp", System.currentTimeMillis()); + + String replyTopic = topic + BusinessConstant._REPLY; + mqttPushService.pushMessageByClient1(replyTopic, message.toString()); + log.info("Q20 requests --> 飞行器请求充电已自动回复, topic: {}, voltage: {}, current: {}", + replyTopic, voltage, current); + } +} diff --git a/admin/src/main/java/com/multictrl/modules/security/config/ShiroConfig.java b/admin/src/main/java/com/multictrl/modules/security/config/ShiroConfig.java index b03fd4d..03cc9e4 100644 --- a/admin/src/main/java/com/multictrl/modules/security/config/ShiroConfig.java +++ b/admin/src/main/java/com/multictrl/modules/security/config/ShiroConfig.java @@ -72,7 +72,6 @@ public class ShiroConfig { filterMap.put("/swagger-resources/**", "anon"); filterMap.put("/captcha", "anon"); filterMap.put("/", "anon"); - filterMap.put("/q20-login.html", "anon"); filterMap.put("/q20-ctrl.html", "anon"); filterMap.put("/srs/**", "anon"); filterMap.put("/mqtt/auth", "anon"); diff --git a/admin/src/main/resources/static/q20-ctrl.html b/admin/src/main/resources/static/q20-ctrl.html index e124711..fc13e0d 100644 --- a/admin/src/main/resources/static/q20-ctrl.html +++ b/admin/src/main/resources/static/q20-ctrl.html @@ -118,6 +118,30 @@ h6.cmd-title { font-size: 12px; color: #e6edf3; font-weight: 600; margin-bottom: + +

+
@@ -1404,13 +1428,75 @@ h6.cmd-title { font-size: 12px; color: #e6edf3; font-weight: 600; margin-bottom: - -