小程序后端模块(子系统)增加水肥机远程操作功能,包括开关注肥、天关搅拌、清除注肥泵报警等功能。
10个文件已添加
750 ■■■■■ 已修改文件
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Cd4MqttParameter.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Com4MqttCtrl.java 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Com4MqttSv.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Dto4MqttBase.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttCdParam.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttFaultCtrl.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttInjectCtrl.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttStirCtrl.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttSv.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Cd4MqttParameter.java
New file
@@ -0,0 +1,15 @@
package com.dy.pipIrrWechat.common;
import lombok.Data;
import lombok.experimental.SuperBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:53
 * @Description
 */
@Data
@SuperBuilder
public class Cd4MqttParameter {
    public Integer no ;//设备编号
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Com4MqttCtrl.java
New file
@@ -0,0 +1,193 @@
package com.dy.pipIrrWechat.common;
import com.dy.common.mw.protocol.Command;
import com.dy.common.mw.protocol4Mqtt.MqttSubMsg;
import com.dy.common.util.Callback;
import com.dy.common.util.IDLongGenerator;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.pipIrrGlobal.command.ComResultWait;
import com.dy.pipIrrGlobal.pojoPr.PrStManure;
import com.dy.pipIrrGlobal.pojoRm.RmCommandHistory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.validation.BindingResult;
import org.springframework.web.client.RestTemplate;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:50
 * @Description
 */
public abstract class Com4MqttCtrl {
    @Autowired
    protected Environment env ;
    @Autowired
    protected RestTemplate restTemplate ;
    @Value("${mw.waitMwRtnResultTimeout}")
    protected int waitMwRtnResultTimeout ;
    @Value("${mw.mqttCallbackUrl_rm}")
    protected String mqttResultSendWebUrl;
    //水肥机对象
    protected PrStManure ctrlPo ;
    //异步等待器
    protected CompletableFuture<MqttSubMsg> feature;
    //命令名称
    protected String comName ;
    //命令日志id
    protected Long comId ;
    /**
     * 发送命令前-1:验证
     * @param comSv
     * @param comCode
     * @param dto
     * @param bindingResult
     * @return
     */
    public BaseResponse<Object> pre1(Com4MqttSv comSv, String comCode, Dto4MqttBase dto, BindingResult bindingResult) {
        if (bindingResult != null && bindingResult.hasErrors()) {
            return BaseResponseUtils.buildError(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        String msg = this.checkDto(dto) ;
        if(msg != null){
            return BaseResponseUtils.buildError("服务端出错," + msg) ;
        }
        return  null ;
    }
    /**
     * 发送命令前-2:获得数据
     * @param comSv
     * @param protocol
     * @param protocolVer
     * @param comCode
     * @param dto
     * @param bindingResult
     * @return
     */
    public BaseResponse<Object> pre2(Com4MqttSv comSv, String protocol, Short protocolVer, String comCode, Dto4MqttBase dto, BindingResult bindingResult) {
        //得到水肥机对象
        ctrlPo = comSv.getManure(dto.getManureId());
        if (ctrlPo == null) {
            return BaseResponseUtils.buildError("服务端出错,从数据库中未得到水肥机数据") ;
        }
        //检查协议
        String msg = comSv.checkProtocol(ctrlPo) ;
        if(msg != null) {
            return BaseResponseUtils.buildError("服务端出错," + msg) ;
        }
        //得到功能码对应的命令名称
        comName = comSv.getCommandName(comCode, protocol, protocolVer) ;
        if(comName == null) {
            return BaseResponseUtils.buildError("服务端出错,未得到功能码对应命令名称") ;
        }
        return  null ;
    }
    /**
     * 发送命令前-3:保存命令日志
     * @param comSv sv对象
     * @param manureId 水肥机ID
     * @param operator 当前用登录用户id(操作人)
     * @param protocol 协议
     * @param protocolVerion 协议
     * @param comCode 功能码
     * @param param 命令参数
     * @return
     */
    public BaseResponse<Object> pre3(Com4MqttSv comSv, Long manureId, Long operator, String protocol, Short protocolVerion, String comCode, Cd4MqttParameter param) {
        comId = new IDLongGenerator().generate();
        //生成并保存命令日志
        RmCommandHistory po = comSv.saveComHistoryPo(comId,
                protocol + protocolVerion ,
                comCode,
                comName,
                manureId,
                ctrlPo.fboxId ,
                param,
                operator);
        if(po == null){
            return BaseResponseUtils.buildError("服务端出错,未能生成并保存命令日志") ;
        }
        return  null ;
    }
    /**
     * 发送命令前-4:准备Feature
     * @return
     */
    public void pre4() {
        feature = new CompletableFuture<>();
        ComResultWait.put(comId, feature);
    }
    /**
     * 发送命令
     * @param comSv
     * @param com
     * @return
     */
    public BaseResponse<Object> doSend(Com4MqttSv comSv, Command com){
        //得到通信中间件发送命令的web URL
        String rqUrl = comSv.get2MwRequestUrl(env, comSv.ContextComSend) ;
        //向通信中间件发送web请求
        BaseResponse res = comSv.sendPostRequest2Mw(restTemplate, rqUrl, com) ;
        //处理通信中间件对web请求的响应
        String msg = comSv.dealMwDealResponse(res) ;
        if(msg != null) {
            return BaseResponseUtils.buildError(msg) ;
        }else{
            return null ;
        }
    }
    /**
     * 发送命令后
     * @return
     */
    public BaseResponse<Object> after(String comCode, Callback callback) {
        try{
            //等待通信中间件通知水肥机执行命令上行数据(命令结果)
            MqttSubMsg subMsg = feature.get(waitMwRtnResultTimeout, TimeUnit.SECONDS);
            return BaseResponseUtils.buildSuccess(this.dealComResult(comCode, subMsg, callback));
        }catch (Exception e){
            return BaseResponseUtils.buildFail("等待通信中间件通知命令结果超时");
        }
    }
    /**
     * 发送命令最后
     * @return
     */
    public void end(){
        try {
            //最后清除CompletableFuture缓存
            if(ComResultWait.contain(comId)){
                ComResultWait.remove(comId);
            }
        }catch (Exception ee){}
    }
    /**
     * 验证
     * @param dto
     * @return
     */
    protected abstract String checkDto(Dto4MqttBase dto) ;
    /**
     * 生成命令返回信息
     */
    protected abstract String dealComResult(String code, MqttSubMsg subMsg, Callback callback);
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Com4MqttSv.java
New file
@@ -0,0 +1,50 @@
package com.dy.pipIrrWechat.common;
import com.dy.pipIrrGlobal.command.Command4MqttSv;
import com.dy.pipIrrGlobal.daoPr.PrStManureMapper;
import com.dy.pipIrrGlobal.daoRm.RmCommandHistoryMapper;
import com.dy.pipIrrGlobal.pojoPr.PrStManure;
import com.dy.pipIrrGlobal.pojoRm.RmCommandHistory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:46
 * @Description
 */
public class Com4MqttSv extends Command4MqttSv {
    @Autowired
    protected PrStManureMapper prStManureDao ;
    @Autowired
    protected RmCommandHistoryMapper rmCommandHistoryDao ;
    public PrStManure getManure(Long manureId){
        return this.getManure(prStManureDao, manureId);
    }
    /**
     * 创建命令日志对象
     *
     * @param comId       主键
     * @param commandCode 功能码
     * @param rtuAddr     阀控器地址
     * @param protocol    通讯协议名称
     * @param param       参数数据
     * @param operator    操作员
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public RmCommandHistory saveComHistoryPo(Long comId,
                                             String protocol,
                                             String commandCode,
                                             String commandName,
                                             Long manureId,
                                             String rtuAddr,
                                             Object param,
                                             Long operator) {
        return this.saveComHistoryPo(rmCommandHistoryDao, comId, protocol, commandCode, commandName, manureId, rtuAddr, param, operator) ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/common/Dto4MqttBase.java
New file
@@ -0,0 +1,31 @@
package com.dy.pipIrrWechat.common;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:49
 * @Description
 */
@Data
public class Dto4MqttBase {
    public static final long serialVersionUID = 202506201459001L;
    /**
     * 水肥机ID
     */
    @NotNull(message = "水肥机不能为空")
    public Long manureId;
    /**
     * 水肥机名称
     */
    public String manureName;
    /**
     * 操作人
     */
    @NotNull(message = "操作人不能为空")
    public Long operator;
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttCdParam.java
New file
@@ -0,0 +1,23 @@
package com.dy.pipIrrWechat.mqtt;
import com.dy.pipIrrWechat.common.Cd4MqttParameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:52
 * @Description
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class MonitorMqttCdParam extends Cd4MqttParameter {
    //启停动作,true是,false否
    //可以执行功能码 00,01,02,03的动作
    public boolean startTrueStopFalse;//
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttDto.java
New file
@@ -0,0 +1,17 @@
package com.dy.pipIrrWechat.mqtt;
import com.dy.pipIrrWechat.common.Dto4MqttBase;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:48
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper=true)
public class MonitorMqttDto extends Dto4MqttBase {
    public static final long serialVersionUID = 202508211449001L;
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttFaultCtrl.java
New file
@@ -0,0 +1,120 @@
package com.dy.pipIrrWechat.mqtt;
import com.alibaba.fastjson2.JSON;
import com.dy.common.aop.SsoAop;
import com.dy.common.mw.protocol.Command;
import com.dy.common.mw.protocol4Mqtt.MqttSubMsg;
import com.dy.common.mw.protocol4Mqtt.pSdV1.CodeSdV1;
import com.dy.common.mw.protocol4Mqtt.pSdV1.ProtocolConstantSdV1;
import com.dy.common.mw.protocol4Mqtt.pSdV1.upVos.ManureVo;
import com.dy.common.util.Callback;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.pipIrrWechat.common.Com4MqttCtrl;
import com.dy.pipIrrWechat.common.Dto4MqttBase;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
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;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 15:00
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "清除故障")
@RestController()
@RequestMapping(path = "mqttFault")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class MonitorMqttFaultCtrl extends Com4MqttCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String Protocol = ProtocolConstantSdV1.protocolName ;
    private static final Short ProtocolVersion = ProtocolConstantSdV1.protocolVer ;
    private static final String ComCode = CodeSdV1.cd_Fault ;
    @Autowired
    private MonitorMqttSv sv ;
    /**
     * 向设备(Mqtt中间件->FBox)发送命令
     * @param dto 前端发来的值对象
     * @param bindingResult 对dto验证的结果
     * @return 返回前端
     */
    @PostMapping(path = "clear", consumes = MediaType.APPLICATION_JSON_VALUE)
    @SsoAop()
    public BaseResponse<Object> send(@RequestBody @Valid MonitorMqttDto dto, BindingResult bindingResult) {
        BaseResponse<Object> res ;
        //发送命令前-1:验证
        res = super.pre1(sv, ComCode, dto, bindingResult);
        if(res == null) {
            //发送命令前-2:获得数据
            res = super.pre2(sv, Protocol, ProtocolVersion, ComCode, dto, bindingResult);
            if (res == null) {
                //发送命令前-3:保存命令日志
                MonitorMqttCdParam comParam = MonitorMqttCdParam.builder().no(ctrlPo.no).startTrueStopFalse(true).build();
                res = super.pre3(sv, dto.manureId, dto.getOperator(), Protocol, ProtocolVersion, ComCode, comParam);
                if (res == null) {
                    //发送命令前-4:准备Feature
                    super.pre4();
                    try {
                        //创建外部命令(发给MQTT->FBox)
                        Command com = sv.createMQTTCommand(ctrlPo.fboxId, "" + comId, Protocol, ProtocolVersion, ComCode);
                        com.rtuResultSendWebUrl = mqttResultSendWebUrl;
                        com.param = comParam ;
                        //发送命令
                        res = super.doSend(sv, com);
                        if (res == null) {
                            //发送命令后
                            res = super.after(ComCode, null);
                        }
                    } catch (Exception e) {
                        res = BaseResponseUtils.buildFail("服务端构造并向通信中间件发送请求时异常" + (e.getMessage() == null ? "" : e.getMessage()));
                    } finally {
                        //最终
                        super.end();
                    }
                }
            }
        }
        return res ;
    }
    @Override
    protected String checkDto(Dto4MqttBase dto) {
        return null;
    }
    @Override
    protected String dealComResult(String code, MqttSubMsg subMsg, Callback callback){
        String msg;
        if(subMsg != null){
            if(subMsg.vo4Up != null && Proxy.isProxyClass(subMsg.vo4Up.getClass())){
                // 获取代理的 InvocationHandler
                InvocationHandler handler = Proxy.getInvocationHandler(subMsg.vo4Up);
                String json = JSON.toJSONString(handler) ;
                ManureVo vo = JSON.parseObject(json, ManureVo.class);
                msg = vo.toString() ;
            }else{
                msg = RtuSuccessMsg ;
            }
        }else{
            msg = RtuSuccessMsg ;
        }
        return msg;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttInjectCtrl.java
New file
@@ -0,0 +1,143 @@
package com.dy.pipIrrWechat.mqtt;
import com.alibaba.fastjson2.JSON;
import com.dy.common.aop.SsoAop;
import com.dy.common.mw.protocol.Command;
import com.dy.common.mw.protocol4Mqtt.MqttSubMsg;
import com.dy.common.mw.protocol4Mqtt.pSdV1.CodeSdV1;
import com.dy.common.mw.protocol4Mqtt.pSdV1.ProtocolConstantSdV1;
import com.dy.common.mw.protocol4Mqtt.pSdV1.upVos.ManureVo;
import com.dy.common.util.Callback;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.pipIrrWechat.common.Com4MqttCtrl;
import com.dy.pipIrrWechat.common.Dto4MqttBase;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
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;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:56
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "注肥启停")
@RestController()
@RequestMapping(path = "mqttInject")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class MonitorMqttInjectCtrl extends Com4MqttCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String Protocol = ProtocolConstantSdV1.protocolName ;
    private static final Short ProtocolVersion = ProtocolConstantSdV1.protocolVer ;
    private static final String ComCode = CodeSdV1.cd_Inject ;
    @Autowired
    private MonitorMqttSv sv ;
    /**
     * 向设备(Mqtt中间件->FBox)发送命令
     * @param dto 前端发来的值对象
     * @param bindingResult 对dto验证的结果
     * @return 返回前端
     */
    @PostMapping(path = "start", consumes = MediaType.APPLICATION_JSON_VALUE)
    @SsoAop()
    public BaseResponse<Object> start(@RequestBody @Valid MonitorMqttDto dto, BindingResult bindingResult) {
        return this.send(dto, bindingResult, true) ;
    }
    /**
     * 向设备(Mqtt中间件->FBox)发送命令
     * @param dto 前端发来的值对象
     * @param bindingResult 对dto验证的结果
     * @return 返回前端
     */
    @PostMapping(path = "stop", consumes = MediaType.APPLICATION_JSON_VALUE)
    @SsoAop()
    public BaseResponse<Object> stop(@RequestBody @Valid MonitorMqttDto dto, BindingResult bindingResult) {
        return this.send(dto, bindingResult, false) ;
    }
    /**
     * 向设备(Mqtt中间件->FBox)发送命令
     * @param dto 前端发来的值对象
     * @param bindingResult 对dto验证的结果
     * @return 返回前端
     */
    private BaseResponse<Object> send(MonitorMqttDto dto, BindingResult bindingResult, boolean startTrueStopFalse) {
        BaseResponse<Object> res ;
        //发送命令前-1:验证
        res = super.pre1(sv, ComCode, dto, bindingResult);
        if(res == null) {
            //发送命令前-2:获得数据
            res = super.pre2(sv, Protocol, ProtocolVersion, ComCode, dto, bindingResult);
            if (res == null) {
                //发送命令前-3:保存命令日志
                MonitorMqttCdParam comParam = MonitorMqttCdParam.builder().no(ctrlPo.no).startTrueStopFalse(startTrueStopFalse).build();
                res = super.pre3(sv, dto.manureId, dto.getOperator(), Protocol, ProtocolVersion, ComCode, comParam);
                if (res == null) {
                    //发送命令前-4:准备Feature
                    super.pre4();
                    try {
                        //创建外部命令(发给MQTT->FBox)
                        Command com = sv.createMQTTCommand(ctrlPo.fboxId, "" + comId, Protocol, ProtocolVersion, ComCode);
                        com.rtuResultSendWebUrl = mqttResultSendWebUrl;
                        com.param = comParam ;
                        //发送命令
                        res = super.doSend(sv, com);
                        if (res == null) {
                            //发送命令后
                            res = super.after(ComCode, null);
                        }
                    } catch (Exception e) {
                        res = BaseResponseUtils.buildFail("服务端构造并向通信中间件发送请求时异常" + (e.getMessage() == null ? "" : e.getMessage()));
                    } finally {
                        //最终
                        super.end();
                    }
                }
            }
        }
        return res ;
    }
    @Override
    protected String checkDto(Dto4MqttBase dto) {
        return null;
    }
    @Override
    protected String dealComResult(String code, MqttSubMsg subMsg, Callback callback){
        String msg;
        if(subMsg != null){
            if(subMsg.vo4Up != null && Proxy.isProxyClass(subMsg.vo4Up.getClass())){
                // 获取代理的 InvocationHandler
                InvocationHandler handler = Proxy.getInvocationHandler(subMsg.vo4Up);
                String json = JSON.toJSONString(handler) ;
                ManureVo vo = JSON.parseObject(json, ManureVo.class);
                msg = vo.toString() ;
            }else{
                msg = RtuSuccessMsg ;
            }
        }else{
            msg = RtuSuccessMsg ;
        }
        return msg;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttStirCtrl.java
New file
@@ -0,0 +1,143 @@
package com.dy.pipIrrWechat.mqtt;
import com.alibaba.fastjson2.JSON;
import com.dy.common.aop.SsoAop;
import com.dy.common.mw.protocol.Command;
import com.dy.common.mw.protocol4Mqtt.MqttSubMsg;
import com.dy.common.mw.protocol4Mqtt.pSdV1.CodeSdV1;
import com.dy.common.mw.protocol4Mqtt.pSdV1.ProtocolConstantSdV1;
import com.dy.common.mw.protocol4Mqtt.pSdV1.upVos.ManureVo;
import com.dy.common.util.Callback;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.pipIrrWechat.common.Com4MqttCtrl;
import com.dy.pipIrrWechat.common.Dto4MqttBase;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
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;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:43
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "搅拌启停")
@RestController()
@RequestMapping(path = "mqttStir")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class MonitorMqttStirCtrl extends Com4MqttCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String Protocol = ProtocolConstantSdV1.protocolName ;
    private static final Short ProtocolVersion = ProtocolConstantSdV1.protocolVer ;
    private static final String ComCode = CodeSdV1.cd_Stir ;
    @Autowired
    private MonitorMqttSv sv ;
    /**
     * 向设备(Mqtt中间件->FBox)发送命令
     * @param dto 前端发来的值对象
     * @param bindingResult 对dto验证的结果
     * @return 返回前端
     */
    @PostMapping(path = "start", consumes = MediaType.APPLICATION_JSON_VALUE)
    @SsoAop()
    public BaseResponse<Object> start(@RequestBody @Valid MonitorMqttDto dto, BindingResult bindingResult) {
        return this.send(dto, bindingResult, true) ;
    }
    /**
     * 向设备(Mqtt中间件->FBox)发送命令
     * @param dto 前端发来的值对象
     * @param bindingResult 对dto验证的结果
     * @return 返回前端
     */
    @PostMapping(path = "stop", consumes = MediaType.APPLICATION_JSON_VALUE)
    @SsoAop()
    public BaseResponse<Object> stop(@RequestBody @Valid MonitorMqttDto dto, BindingResult bindingResult) {
        return this.send(dto, bindingResult, false) ;
    }
    /**
     * 向设备(Mqtt中间件->FBox)发送命令
     * @param dto 前端发来的值对象
     * @param bindingResult 对dto验证的结果
     * @return 返回前端
     */
    private BaseResponse<Object> send(MonitorMqttDto dto, BindingResult bindingResult, boolean startTrueStopFalse) {
        BaseResponse<Object> res ;
        //发送命令前-1:验证
        res = super.pre1(sv, ComCode, dto, bindingResult);
        if(res == null) {
            //发送命令前-2:获得数据
            res = super.pre2(sv, Protocol, ProtocolVersion, ComCode, dto, bindingResult);
            if (res == null) {
                //发送命令前-3:保存命令日志
                MonitorMqttCdParam comParam = MonitorMqttCdParam.builder().no(ctrlPo.no).startTrueStopFalse(startTrueStopFalse).build();
                res = super.pre3(sv, dto.manureId, dto.getOperator(), Protocol, ProtocolVersion, ComCode, comParam);
                if (res == null) {
                    //发送命令前-4:准备Feature
                    super.pre4();
                    try {
                        //创建外部命令(发给MQTT->FBox)
                        Command com = sv.createMQTTCommand(ctrlPo.fboxId, "" + comId, Protocol, ProtocolVersion, ComCode);
                        com.rtuResultSendWebUrl = mqttResultSendWebUrl;
                        com.param = comParam ;
                        //发送命令
                        res = super.doSend(sv, com);
                        if (res == null) {
                            //发送命令后
                            res = super.after(ComCode, null);
                        }
                    } catch (Exception e) {
                        res = BaseResponseUtils.buildFail("服务端构造并向通信中间件发送请求时异常" + (e.getMessage() == null ? "" : e.getMessage()));
                    } finally {
                        //最终
                        super.end();
                    }
                }
            }
        }
        return res ;
    }
    @Override
    protected String checkDto(Dto4MqttBase dto) {
        return null;
    }
    @Override
    protected String dealComResult(String code, MqttSubMsg subMsg, Callback callback){
        String msg;
        if(subMsg != null){
            if(subMsg.vo4Up != null && Proxy.isProxyClass(subMsg.vo4Up.getClass())){
                // 获取代理的 InvocationHandler
                InvocationHandler handler = Proxy.getInvocationHandler(subMsg.vo4Up);
                String json = JSON.toJSONString(handler) ;
                ManureVo vo = JSON.parseObject(json, ManureVo.class);
                msg = vo.toString() ;
            }else{
                msg = RtuSuccessMsg ;
            }
        }else{
            msg = RtuSuccessMsg ;
        }
        return msg;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/mqtt/MonitorMqttSv.java
New file
@@ -0,0 +1,15 @@
package com.dy.pipIrrWechat.mqtt;
import com.dy.pipIrrWechat.common.Com4MqttSv;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
 * @Author: liurunyu
 * @Date: 2025/8/21 14:45
 * @Description
 */
@Slf4j
@Service()
public class MonitorMqttSv extends Com4MqttSv {
}