优化系统逻辑

This commit is contained in:
weitang 2025-05-12 14:35:37 +08:00
parent ee79c8c600
commit 17c349c5e7
17 changed files with 240 additions and 175 deletions

View File

@ -17,9 +17,9 @@ package com.yfd.platform.component.iec104.client;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yfd.platform.component.iec104.config.Iec104Config;
import com.yfd.platform.component.utils.OptimizedThreadPool;
import com.yfd.platform.component.iec104.server.Iec104Master;
import com.yfd.platform.component.iec104.server.Iec104MasterFactory;
import com.yfd.platform.component.utils.OptimizedThreadPool;
import com.yfd.platform.modules.auxcontrol.domain.GatewayDevice;
import com.yfd.platform.modules.auxcontrol.mapper.GatewayDeviceMapper;
import lombok.RequiredArgsConstructor;
@ -61,30 +61,30 @@ public class IEC104ClientRunner implements ApplicationRunner {
GatewayDevice::getIpAddr, GatewayDevice::getIecAddr);
queryWrapper.orderByAsc(GatewayDevice::getDeviceCode);
List<GatewayDevice> list = gatewayDeviceMapper.selectList(queryWrapper);
if (list.size() > 0) {
for (GatewayDevice gatewayDevice : list) {
Iec104Config iec104Config = new Iec104Config();
iec104Config.setFrameAmountMax((short) 10);
short terminnalAddress = gatewayDevice.getIecAddr().shortValue();
//通讯网关机地址
iec104Config.setTerminnalAddress(terminnalAddress);
iec104Config.setSlaveCode(gatewayDevice.getDeviceCode());
iec104Config.setSlaveIP(gatewayDevice.getIpAddr());
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
Iec104Master iec104server = Iec104MasterFactory.createTcpClientMaster(iec104Config.getSlaveIP(),
2404);
try {
iec104server.setDataHandler(new MasterSysDataHandler()).setConfig(iec104Config).run();
} catch (Exception e) {
log.error(String.format("%s-对应的终端连接失败!", iec104Config.getSlaveIP()));
}
});
threadPool.shutdown();
}
}
// if (list.size() > 0) {
// for (GatewayDevice gatewayDevice : list) {
// Iec104Config iec104Config = new Iec104Config();
// iec104Config.setFrameAmountMax((short) 10);
// short terminnalAddress = gatewayDevice.getIecAddr().shortValue();
// //通讯网关机地址
// iec104Config.setTerminnalAddress(terminnalAddress);
// iec104Config.setSlaveCode(gatewayDevice.getDeviceCode());
// iec104Config.setSlaveIP(gatewayDevice.getIpAddr());
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// Iec104Master iec104server = Iec104MasterFactory.createTcpClientMaster(iec104Config.getSlaveIP(),
// 2404);
// try {
// iec104server.setDataHandler(new MasterSysDataHandler()).setConfig(iec104Config).run();
//
// } catch (Exception e) {
// log.error(String.format("%s-对应的终端连接失败!", iec104Config.getSlaveIP()));
// }
// });
// threadPool.shutdown();
// }
//
// }
}
}

View File

@ -60,26 +60,26 @@ public class ControlManageUtil {
* 启动S发送S确认帧 的任务
*/
public void startSendFrameTask() {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
while (true) {
try {
synchronized (sendSframeLock) {
if (frameAmount >= frameAmountMax) {
// 查过最大帧 的数量就要发送一个确认帧出去
byte[] control = Iec104Util.getScontrol(accept);
MessageDetail ruleDetail104 = new MessageDetail(control);
ctx.channel().writeAndFlush(Encoder104.encoder(ruleDetail104));
frameAmount = 0;
}
sendSframeLock.wait();
}
} catch (Exception e) {
LOGGER.error("Exception caught", e);
}
}
});
threadPool.shutdown();
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// while (true) {
// try {
// synchronized (sendSframeLock) {
// if (frameAmount >= frameAmountMax) {
// // 查过最大帧 的数量就要发送一个确认帧出去
// byte[] control = Iec104Util.getScontrol(accept);
// MessageDetail ruleDetail104 = new MessageDetail(control);
// ctx.channel().writeAndFlush(Encoder104.encoder(ruleDetail104));
// frameAmount = 0;
// }
// sendSframeLock.wait();
// }
// } catch (Exception e) {
// LOGGER.error("Exception caught", e);
// }
// }
// });
// threadPool.shutdown();
}

View File

@ -72,22 +72,22 @@ public class ScheduledTaskPool {
* @Description: 发送测试帧
*/
private void sendTestFrame() {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
try {
BootNettyClientChannel channel = BootNettyClientChannelCache.get(ctx.channel().id().asShortText());
if(ObjUtil.isNotEmpty(channel )){
String slaveIp = channel .getCode();
LOGGER.info(String.format("向从站[%s]发送测试链路指令!",slaveIp ));
ctx.channel().writeAndFlush(BasicInstruction104.TESTFR);
//对时指令
ctx.channel().writeAndFlush(BasicInstruction104.getTimeScale104());
}
} catch (Exception e) {
LOGGER.error("Exception caught", e);
}
});
threadPool.shutdown();
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// try {
// BootNettyClientChannel channel = BootNettyClientChannelCache.get(ctx.channel().id().asShortText());
// if(ObjUtil.isNotEmpty(channel )){
// String slaveIp = channel .getCode();
// LOGGER.info(String.format("向从站[%s]发送测试链路指令!",slaveIp ));
// ctx.channel().writeAndFlush(BasicInstruction104.TESTFR);
// //对时指令
// ctx.channel().writeAndFlush(BasicInstruction104.getTimeScale104());
// }
// } catch (Exception e) {
// LOGGER.error("Exception caught", e);
// }
// });
// threadPool.shutdown();
}
@ -101,21 +101,21 @@ public class ScheduledTaskPool {
}
private void sendGeneralCall() {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
try {
BootNettyClientChannel channel = BootNettyClientChannelCache.get(ctx.channel().id().asShortText());
if (ObjUtil.isNotEmpty(channel)) {
String slaveIp = channel.getCode();
MessageDetail messageDetail = BasicInstruction104.getGeneralCallRuleDetail104();
LOGGER.info(String.format("向从站[%s]发送总召唤指令[%s]", slaveIp, messageDetail.getHexString()));
ctx.channel().writeAndFlush(messageDetail);
}
} catch (Exception e) {
LOGGER.error("Exception caught", e);
}
});
threadPool.shutdown();
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// try {
// BootNettyClientChannel channel = BootNettyClientChannelCache.get(ctx.channel().id().asShortText());
// if (ObjUtil.isNotEmpty(channel)) {
// String slaveIp = channel.getCode();
// MessageDetail messageDetail = BasicInstruction104.getGeneralCallRuleDetail104();
// LOGGER.info(String.format("向从站[%s]发送总召唤指令[%s]", slaveIp, messageDetail.getHexString()));
// ctx.channel().writeAndFlush(messageDetail);
// }
// } catch (Exception e) {
// LOGGER.error("Exception caught", e);
// }
// });
// threadPool.shutdown();
}
public void stopSendCommandTask() {

View File

@ -49,17 +49,17 @@ public class Iec104ClientHandler extends SimpleChannelInboundHandler<MessageDeta
BootNettyClientChannelCache.remove(ctx.channel().id().asShortText());
BootNettyClientChannelCache.save(ctx.channel().id().asShortText(),Channel);
if (dataHandler != null) {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
try {
dataHandler.handlerAdded(new ChannelHandlerImpl(ctx));
} catch (Exception e) {
LOGGER.error("Exception caught", e);
}
});
threadPool.shutdown();
}
// if (dataHandler != null) {
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// try {
// dataHandler.handlerAdded(new ChannelHandlerImpl(ctx));
// } catch (Exception e) {
// LOGGER.error("Exception caught", e);
// }
// });
// threadPool.shutdown();
// }
}
@Override
@ -76,18 +76,18 @@ public class Iec104ClientHandler extends SimpleChannelInboundHandler<MessageDeta
@Override
public void channelRead0(ChannelHandlerContext ctx, MessageDetail ruleDetail104) throws IOException {
if (dataHandler != null) {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
try {
dataHandler.channelRead(new ChannelHandlerImpl(ctx), ruleDetail104);
} catch (Exception e) {
// TODO Auto-generated catch block
LOGGER.error("Exception caught", e);
}
});
threadPool.shutdown();
}
// if (dataHandler != null) {
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// try {
// dataHandler.channelRead(new ChannelHandlerImpl(ctx), ruleDetail104);
// } catch (Exception e) {
// // TODO Auto-generated catch block
// LOGGER.error("Exception caught", e);
// }
// });
// threadPool.shutdown();
// }
}

View File

@ -40,17 +40,17 @@ public class Iec104TcpSlaveHandler extends SimpleChannelInboundHandler<MessageDe
* 启动
*/
Iec104ThreadLocal.getControlPool().startSendFrameTask();
if (dataHandler != null) {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
try {
dataHandler.handlerAdded(new ChannelHandlerImpl(ctx));
} catch (Exception e) {
LOGGER.error("Exception caught", e);
}
});
threadPool.shutdown();
}
// if (dataHandler != null) {
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// try {
// dataHandler.handlerAdded(new ChannelHandlerImpl(ctx));
// } catch (Exception e) {
// LOGGER.error("Exception caught", e);
// }
// });
// threadPool.shutdown();
// }
}
/**
@ -65,18 +65,18 @@ public class Iec104TcpSlaveHandler extends SimpleChannelInboundHandler<MessageDe
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, MessageDetail ruleDetail104) throws Exception {
if (dataHandler != null) {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> {
try {
dataHandler.channelRead(new ChannelHandlerImpl(ctx), ruleDetail104);
} catch (Exception e) {
LOGGER.error("Exception caught", e);
}
});
threadPool.shutdown();
}
// if (dataHandler != null) {
//
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> {
// try {
// dataHandler.channelRead(new ChannelHandlerImpl(ctx), ruleDetail104);
// } catch (Exception e) {
// LOGGER.error("Exception caught", e);
// }
// });
// threadPool.shutdown();
// }
}
/**

View File

@ -45,10 +45,10 @@ public class IEC61850ClientRunner implements ApplicationRunner {
queryWrapper.orderByAsc(GatewayDevice::getDeviceCode);
List<GatewayDevice> list = gatewayDeviceMapper.selectList(queryWrapper);
if (!list.isEmpty()) {
for (GatewayDevice systemDevice : list) {
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(() -> iec61850Service.connect(systemDevice));
}
// for (GatewayDevice systemDevice : list) {
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(() -> iec61850Service.connect(systemDevice));
// }
}
}

View File

@ -9,6 +9,7 @@ import com.yfd.platform.modules.auxcontrol.service.IDeviceWorkDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -72,7 +73,7 @@ public class DeviceWorkDataController {
// 构建xAxis和series数据
List<String> xAxisData = new ArrayList<>();
List<Double> seriesData = new ArrayList<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH分mm秒");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH时mm分");
for (LocalDateTime slot : minuteSlots) {
xAxisData.add(slot.format(formatter));
BigDecimal value = minuteDataMap.getOrDefault(slot, BigDecimal.ZERO);
@ -123,4 +124,5 @@ public class DeviceWorkDataController {
return ResponseResult.success();
}
}

View File

@ -129,7 +129,7 @@ public class DeviceSignal implements Serializable {
/**
* 信号当前状态
*/
private BigDecimal ycValue;
private String ycValue;
/**
* 备用1

View File

@ -57,7 +57,8 @@ public class DeviceSignalServiceImpl extends ServiceImpl<DeviceSignalMapper, Dev
deviceSignal.setYxValue(Integer.parseInt(value));
} else {
// 遥测
deviceSignal.setYcValue(Convert.toBigDecimal(value));
deviceSignal.setYcValue(value);
// deviceSignal.setYcValue(Convert.toBigDecimal(value));
}
} catch (NumberFormatException e) {
// 处理转换异常例如返回false或抛出更具体的异常

View File

@ -167,17 +167,17 @@ public class GatewayDeviceServiceImpl extends ServiceImpl<GatewayDeviceMapper, G
log.error("Exception caught", e);
}
}
Runnable runnable = () -> {
Iec104Master iec104server = Iec104MasterFactory.createTcpClientMaster(iec104Config.getSlaveIP(), 2404);
try {
iec104server.setDataHandler(new MasterSysDataHandler()).setConfig(iec104Config).run();
} catch (Exception e) {
EventLoopGroupManager.shutdownEventLoopGroup(ip);
log.error(String.format("%s-对应的终端连接失败!", iec104Config.getSlaveIP()));
}
};
OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
threadPool.execute(runnable);
// Runnable runnable = () -> {
// Iec104Master iec104server = Iec104MasterFactory.createTcpClientMaster(iec104Config.getSlaveIP(), 2404);
// try {
// iec104server.setDataHandler(new MasterSysDataHandler()).setConfig(iec104Config).run();
// } catch (Exception e) {
// EventLoopGroupManager.shutdownEventLoopGroup(ip);
// log.error(String.format("%s-对应的终端连接失败!", iec104Config.getSlaveIP()));
// }
// };
// OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
// threadPool.execute(runnable);
}
return true;

View File

@ -2,18 +2,19 @@ package com.yfd.platform.modules.patroltask.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.beanit.iec61850bean.BdaBoolean;
import com.beanit.iec61850bean.BdaTimestamp;
import com.yfd.platform.component.WebSocketServer;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.auxcontrol.mapper.DeviceSignalMapper;
import com.yfd.platform.modules.auxcontrol.service.IDeviceWorkDataService;
import com.yfd.platform.modules.basedata.domain.DeviceChannel;
import com.yfd.platform.modules.basedata.domain.SubstationDevice;
import com.yfd.platform.modules.basedata.service.IDeviceChannelService;
import com.yfd.platform.modules.basedata.service.ISubstationDeviceService;
import com.yfd.platform.modules.patroltask.domain.AlarmLog;
@ -57,6 +58,8 @@ public class AlarmLogController {
@Resource
private IDeviceWorkDataService deviceWorkDataService;
@Resource
private DeviceSignalMapper deviceSignalMapper;
@GetMapping("/getAlarmLogList")
@ApiOperation("查询报警信息")
@ -291,14 +294,36 @@ public class AlarmLogController {
@GetMapping("/createAlarmData")
@ApiOperation("生成报警")
public ResponseResult createAlarmData(String from,String type,String slaveIp,String address,String value) {
deviceWorkDataService.insertData(from, type, slaveIp, address, value);
alarmLogService.doAlaramRecord(from, type, slaveIp, address, value);
// alarmLogService.doAlaramRecord("IEC61850", "yx", "192.168.1.1", "10", "2");
public ResponseResult createAlarmData(String from, String type, String slaveIp, String address, String value) {
deviceWorkDataService.insertData(from, slaveIp, address, value, getCurrentTime());
alarmLogService.doAlaramRecord(from, type, slaveIp, address, value);
// alarmLogService.doAlaramRecord("IEC61850", "yx", "192.168.1.1", "10", "2");
return ResponseResult.success();
}
public static String getCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
return sdf.format(new Date());
}
@PostMapping("/sendAnalogData")
@ApiOperation("批量发送数据")
public ResponseResult sendAnalogData(String from, String type, String slaveIp, String address, String value) {
if ("yc".equals(type)) {
//更新信号数据值
deviceSignalMapper.updateDeviceSignalValue_yc(address, value, getCurrentTime());
//插入历史数据
deviceWorkDataService.insertData("IEC61850", null, address, value, getCurrentTime());
//执行报警处理
alarmLogService.doAlaramRecord("IEC61850", "yc", null, address, value);
}
if ("yx".equals(type)) {
//更新信号状态
deviceSignalMapper.updateDeviceSignalValue_yx(address, value, getCurrentTime());
//执行报警处理生成设备自身报警记录status=1
alarmLogService.doAlaramRecord("IEC61850", "yx", null, address, value);
}
return ResponseResult.success();
}
}

View File

@ -207,4 +207,6 @@ public interface TaskResultMapper extends BaseMapper<TaskResult> {
Page<Map<String, Object>> getResultByPatroldevice(Page<Map<String, Object>> page, String internationalId,String mainDeviceId, String taskName, String recognitionType, String valid,String isReport,String startDate,String endDate);
List<TaskResult> getNonCoherentResult(String areaId,String bayId,String mainDeviceId,String componentId,String recognitionTypeList,String meterType,String resultId,String taskTodoId,String phase);
Page<Map<String, Object>> getHistoryDevice(Page<Map<String, Object>> page, String startDate, String endDate, String deviceId);
}

View File

@ -1983,29 +1983,30 @@ public class TaskTodoServiceImpl extends ServiceImpl<TaskTodoMapper, TaskTodo> i
@Override
public Page<Map<String, Object>> getHistoryDevice(Page<Map<String, Object>> page, String startDate,
String endDate, String deviceId) {
LambdaQueryWrapper<TaskResult> queryWrapper = new LambdaQueryWrapper<>();
String startFormat = "";
queryWrapper.ne(TaskResult::getFlag, "0");
if (StrUtil.isNotBlank(startDate)) {
Date parseStart = DateUtil.parse(startDate);
//一天的开始
Date beginOfDay = DateUtil.beginOfDay(parseStart);
startFormat = DateUtil.format(beginOfDay, "yyyy-MM-dd HH:mm:ss");
queryWrapper.ge(TaskResult::getPatroldeviceDate, startFormat);
}
String endFormat = "";
if (StrUtil.isNotBlank(startDate)) {
Date parseEnd = DateUtil.parse(endDate);
//一天的结束
Date endOfDay = DateUtil.endOfDay(parseEnd);
endFormat = DateUtil.format(endOfDay, "yyyy-MM-dd HH:mm:ss");
queryWrapper.le(TaskResult::getPatroldeviceDate, endFormat);
}
if (StrUtil.isNotBlank(deviceId)) {
queryWrapper.eq(TaskResult::getDeviceId, deviceId);
}
queryWrapper.orderByAsc(TaskResult::getPatroldeviceDate);
return taskResultMapper.selectMapsPage(page, queryWrapper);
// LambdaQueryWrapper<TaskResult> queryWrapper = new LambdaQueryWrapper<>();
// String startFormat = "";
// queryWrapper.ne(TaskResult::getFlag, "0");
// if (StrUtil.isNotBlank(startDate)) {
// Date parseStart = DateUtil.parse(startDate);
// //一天的开始
// Date beginOfDay = DateUtil.beginOfDay(parseStart);
// startFormat = DateUtil.format(beginOfDay, "yyyy-MM-dd HH:mm:ss");
// queryWrapper.ge(TaskResult::getPatroldeviceDate, startFormat);
// }
// String endFormat = "";
// if (StrUtil.isNotBlank(startDate)) {
// Date parseEnd = DateUtil.parse(endDate);
// //一天的结束
// Date endOfDay = DateUtil.endOfDay(parseEnd);
// endFormat = DateUtil.format(endOfDay, "yyyy-MM-dd HH:mm:ss");
// queryWrapper.le(TaskResult::getPatroldeviceDate, endFormat);
// }
// if (StrUtil.isNotBlank(deviceId)) {
// queryWrapper.eq(TaskResult::getDeviceId, deviceId);
// }
// queryWrapper.orderByAsc(TaskResult::getPatroldeviceDate);
// return taskResultMapper.selectMapsPage(page, queryWrapper);
return taskResultMapper.getHistoryDevice(page, startDate, endDate, deviceId);
}
/**********************************

View File

@ -138,7 +138,7 @@ httpserver: #配置http请求访问的地址
app:
patrolserver: #巡视主机服务器
ip: 192.168.1.20
httpport: 8070
httpport: 8090
tcpport: 10014
udpport: 8090
appname:

View File

@ -51,10 +51,10 @@
c.ip_addr = #{slaveIp}
</if>
<if test="type=='yx'">
and b.yx_addr = #{address}
and b.yx_addr = #{type}
</if>
<if test="type=='yc'">
and b.yc_addr = #{address}
and b.yc_addr = #{type}
</if>
limit 1
</select>

View File

@ -6,6 +6,7 @@
SELECT
station_id,
device_id,
systemcode,
device_name,
signal_id,
signal_name,
@ -15,7 +16,10 @@
FROM
fk_device_work_data
WHERE 1=1
<if test="signalId != null and signalId != ''">
AND signal_id=#{signalId}
</if>
<if test="startDate != null and startDate != ''">
AND start_time &gt;= #{startDate}
</if>

View File

@ -881,4 +881,34 @@ ORDER BY
<select id="getValueByDeviceId" resultType="java.util.Map">
SELECT * FROM iis_recognition WHERE device_id=#{deviceId}
</select>
<select id="getHistoryDevice" resultType="java.util.Map">
SELECT
t.*,
CASE
WHEN t.flag = '4' THEN
'识别失败'
WHEN t.flag = '6' THEN
'采集失败'
WHEN t.valid1 = '2' THEN
'异常' -- 或者你可以设置一个默认值
WHEN t.valid1 = '1' THEN
'正常' -- 或者你可以设置一个默认值
ELSE NULL
END AS analysisResult
FROM
( SELECT *, CASE WHEN revise_valid = '0' THEN '1' WHEN revise_valid = '1' THEN '2' ELSE valid END AS valid1 FROM iis_task_result ) t
WHERE
t.datastatus = '1'
AND t.flag != '0'
<if test="deviceId != null and deviceId != ''">
AND t.device_id = #{deviceId}
</if>
<if test="startDate != null and startDate != ''">
AND t.patroldevice_date &gt;= #{startDate}
</if>
<if test="endDate != null and endDate != ''">
AND t.patroldevice_date &lt;= #{endDate}
</if>
</select>
</mapper>