This commit is contained in:
磷叶 2025-05-16 17:33:46 +08:00
parent 66336eeed4
commit 33b469cdbc
17 changed files with 327 additions and 102 deletions

View File

@ -122,4 +122,9 @@ public class CacheConstants
* 操作日志队列
*/
public static final String OPER_LOG_QUEUE = "oper_log_queue";
/**
* 设备更新物联网状态队列
*/
public static final String DEVICE_UPDATE_IOT_QUEUE = "device_update_iot_queue";
}

View File

@ -140,7 +140,7 @@ public class MathUtils {
for (int i = 1; i < values.length; i++) {
BigDecimal value = values[i];
if (value == null) {
return null;
continue;
}
if (min == null || value.compareTo(min) < 0) {
min = value;

View File

@ -3,6 +3,7 @@ package com.ruoyi.bst.areaSub.service.impl;
import java.util.Collections;
import java.util.List;
import com.ruoyi.common.utils.ServiceUtil;
import org.locationtech.jts.geom.Geometry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -106,15 +107,19 @@ public class AreaSubServiceImpl implements AreaSubService
@Override
public int updateAreaSub(AreaSub areaSub)
{
AreaSubVO old = selectAreaSubById(areaSub.getId());
ServiceUtil.assertion(old == null, "ID为%s的待修改子区域不存在", areaSub.getId());
// 将边界值转Geometry对象
if (areaSub.getBoundaryStr() != null) {
Geometry geometry = GeoUtils.toGeometry(areaSub.getBoundaryStr());
areaSub.setBoundary(GeoUtils.wkt(geometry));
}
int result = areaSubMapper.updateAreaSub(areaSub);
if (result > 0) {
this.clearCache(areaSub.getAreaId());
this.clearCache(old.getAreaId());
}
return result;
@ -143,7 +148,7 @@ public class AreaSubServiceImpl implements AreaSubService
* @return 结果
*/
@Override
public int logicDel(List<Long> ids) {
public int logicDel(List<Long> ids) {
if (CollectionUtils.isEmptyElement(ids)) {
return 0;
}
@ -155,16 +160,16 @@ public class AreaSubServiceImpl implements AreaSubService
// 删除数据库
int result = areaSubMapper.logicDel(ids);
// 删除缓存
if (result > 0) {
for (AreaSubVO areaSub : list) {
this.clearCache(areaSub.getAreaId());
}
}
return result;
}
}
private List<AreaSubVO> selectAreaSubByIds(List<Long> ids) {
if (CollectionUtils.isEmptyElement(ids)) {

View File

@ -126,6 +126,10 @@ public class CommandLogServiceImpl implements CommandLogService
po.setType(CommandLogType.BLUETOOTH.getType());
int rows = this.addLog(po, loginUser);
if (rows > 0) {
// TODO 记录定位日志
// 记录操作日志
OperLog operLog = new OperLog();
operLog.setTitle(po.getReason() + "(蓝牙)");

View File

@ -168,4 +168,11 @@ public interface DeviceMapper
*/
int updateByQuerySimple(@Param("data") Device data, @Param("query") DeviceQuery query);
/**
* 批量更新IOT数据
* @param list
* @return
*/
int batchUpdateIot(@Param("list") List<Device> list);
}

View File

@ -498,4 +498,106 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
</update>
<!-- batchUpdateIot -->
<update id="batchUpdateIot">
update bst_device
<trim prefix="SET" suffixOverrides=",">
<if test="list[0].voltage != null">
voltage = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.voltage}
</foreach>
else voltage end,
</if>
<if test="list[0].signalStrength != null">
signal_strength = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.signalStrength}
</foreach>
else signal_strength end,
</if>
<if test="list[0].quality != null">
quality = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.quality}
</foreach>
else quality end,
</if>
<if test="list[0].satellites != null">
satellites = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.satellites}
</foreach>
else satellites end,
</if>
<if test="list[0].iotStatus != null">
iot_status = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.iotStatus}
</foreach>
else iot_status end,
</if>
<if test="list[0].longitude != null">
longitude = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.longitude}
</foreach>
else longitude end,
</if>
<if test="list[0].latitude != null">
latitude = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.latitude}
</foreach>
else latitude end,
</if>
<if test="list[0].remainingPower != null">
remaining_power = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.remainingPower}
</foreach>
else remaining_power end,
</if>
<if test="list[0].lastTime != null">
last_time = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.lastTime}
</foreach>
else last_time end,
</if>
<if test="list[0].lastLocationTime != null">
last_location_time = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.lastLocationTime}
</foreach>
else last_location_time end,
</if>
<if test="list[0].onlineStatus != null">
online_status = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.onlineStatus}
</foreach>
else online_status end,
</if>
<if test="list[0].lastOnlineTime != null">
last_online_time = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.lastOnlineTime}
</foreach>
else last_online_time end,
</if>
<if test="list[0].softwareVersion != null">
software_version = case mac
<foreach collection="list" item="item">
when #{item.mac} then #{item.softwareVersion}
</foreach>
else software_version end,
</if>
</trim>
where mac in
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.mac}
</foreach>
</update>
</mapper>

View File

@ -231,4 +231,11 @@ public interface DeviceService
* @return
*/
public int updateByQuerySimple(Device data, DeviceQuery query);
/**
* 批量更新IOT数据
* @param list
* @return
*/
public int batchUpdateIot(List<Device> list);
}

View File

@ -1,11 +1,9 @@
package com.ruoyi.bst.device.service.impl;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -25,7 +23,6 @@ import com.ruoyi.bst.device.mapper.DeviceMapper;
import com.ruoyi.bst.device.service.DeviceIotService;
import com.ruoyi.bst.device.service.DeviceService;
import com.ruoyi.bst.device.utils.DeviceUtil;
import com.ruoyi.bst.locationLog.domain.LocationLog;
import com.ruoyi.bst.locationLog.service.LocationLogConverter;
import com.ruoyi.bst.orderDevice.domain.enums.OrderDeviceStatus;
import com.ruoyi.common.constant.CacheConstants;
@ -33,6 +30,7 @@ import com.ruoyi.common.constants.ServiceCode;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.enums.LogBizType;
import com.ruoyi.common.utils.MathUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
@ -44,6 +42,7 @@ import com.ruoyi.iot.enums.IotHttpStatus;
import com.ruoyi.iot.service.IotService;
import com.ruoyi.iot.service.impl.DeviceOnlineStatus;
import com.ruoyi.iot.util.IotUtil;
import com.ruoyi.system.operLog.service.OperLogService;
import lombok.extern.slf4j.Slf4j;
@ -75,6 +74,9 @@ public class DeviceIotServiceImpl implements DeviceIotService {
@Autowired
private RedisCache redisCache;
@Autowired
private OperLogService operLogService;
private final static Integer SUB_FAST = 5; // 上报频率
private final static Integer SUB_SLOW = 300; // 上报频率
@ -117,7 +119,7 @@ public class DeviceIotServiceImpl implements DeviceIotService {
if (rows > 0) {
// 发送命令开锁
CommandResponse res = iotService.unlock(device, SUB_FAST, reason);
CommandResponse res = iotService.unlock(device, SUB_FAST, reason, 3);
boolean iot = IotUtil.isSuccess(res);
ServiceUtil.assertion(requiredIot && !iot, IotUtil.getMsg(res), ServiceCode.IOT_FAILED);
vo.setIot(iot);
@ -126,11 +128,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
return rows;
});
// 异步执行3次设备监控
if (!requiredIot) {
this.asyncMonitorCount(device.getId(), 3);
}
return vo;
}
@ -168,10 +165,10 @@ public class DeviceIotServiceImpl implements DeviceIotService {
CommandResponse res = null;
if (DeviceStatus.TEMP_LOCKED.getCode().equals(data.getStatus())) {
// 临时锁车
res = iotService.tempLock(device, SUB_SLOW, reason);
res = iotService.tempLock(device, SUB_SLOW, reason, 3);
} else {
// 锁车
res = iotService.lock(device, SUB_SLOW, reason);
res = iotService.lock(device, SUB_SLOW, reason, 3);
}
boolean iot = IotUtil.isSuccess(res);
ServiceUtil.assertion(requiredIot && !iot, IotUtil.getMsg(res), ServiceCode.IOT_FAILED);
@ -181,11 +178,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
return rows;
});
// 异步执行3次设备监控
if (!requiredIot) {
this.asyncMonitorCount(device.getId(), 3);
}
return vo;
}
@ -214,7 +206,7 @@ public class DeviceIotServiceImpl implements DeviceIotService {
if (rows > 0) {
// 发送命令锁车
CommandResponse res = iotService.qLock(device, SUB_FAST, reason);
CommandResponse res = iotService.qLock(device, SUB_FAST, reason, 3);
boolean iot = IotUtil.isSuccess(res);
ServiceUtil.assertion(requiredIot && !iot, IotUtil.getMsg(res), ServiceCode.IOT_FAILED);
vo.setIot(iot);
@ -223,11 +215,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
return rows;
});
// 异步执行3次设备监控
if (!requiredIot) {
this.asyncMonitorCount(device.getId(), 3);
}
return vo;
}
@ -317,6 +304,7 @@ public class DeviceIotServiceImpl implements DeviceIotService {
return 0;
}
Device data = new Device();
data.setMac(device.getMac());
data.setVoltage(device.getVoltage());
data.setSignalStrength(device.getSignalStrength());
data.setQuality(device.getQuality());
@ -330,10 +318,11 @@ public class DeviceIotServiceImpl implements DeviceIotService {
data.setOnlineStatus(device.getOnlineStatus());
data.setLastOnlineTime(device.getLastOnlineTime());
data.setSoftwareVersion(device.getSoftwareVersion());
DeviceQuery query = new DeviceQuery();
query.setId(device.getId());
query.setEqMac(device.getMac());
return deviceMapper.updateByQuerySimple(data, query);
// 添加到缓存队列
redisCache.rightPush(CacheConstants.DEVICE_UPDATE_IOT_QUEUE, data);
return 1;
}
@Override
@ -388,10 +377,20 @@ public class DeviceIotServiceImpl implements DeviceIotService {
}
// 判断电门与设备锁状态是否一致不一致则发送命令
if (DeviceLockStatus.OPEN.getCode().equals(device.getLockStatus()) && !DeviceQuality.OPEN.getCode().equals(device.getQuality())) {
iotService.unlock(device, SUB_FAST, "【设备监控】电门异常未开启");
CommandResponse res = iotService.unlock(device, SUB_FAST, "重新尝试开锁", 1);
if (device.getOrderId() != null) {
operLogService.operSysLog("【设备监控】发现未开启的车辆", IotUtil.isSuccess(res), LogBizType.ORDER, device.getOrderId(), device);
} else {
operLogService.operSysLog("【设备监控】发现未开启的车辆", IotUtil.isSuccess(res), LogBizType.DEVICE, device.getId(), device);
}
}
if (DeviceLockStatus.CLOSE.getCode().equals(device.getLockStatus()) && !DeviceQuality.CLOSE.getCode().equals(device.getQuality())) {
iotService.lock(device, SUB_SLOW, "【设备监控】电门异常未关闭");
CommandResponse res = iotService.lock(device, SUB_SLOW, "重新尝试锁车", 1);
if (device.getOrderId() != null) {
operLogService.operSysLog("【设备监控】发现未关闭的车辆", IotUtil.isSuccess(res), LogBizType.ORDER, device.getOrderId(), device);
} else {
operLogService.operSysLog("【设备监控】发现未关闭的车辆", IotUtil.isSuccess(res), LogBizType.DEVICE, device.getId(), device);
}
}
}
@ -402,15 +401,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
this.monitor(device);
}
private void asyncMonitorCount(Long deviceId, int count) {
scheduledExecutorService.schedule(() -> {
if (count > 0) {
this.monitor(Collections.singletonList(deviceId));
this.asyncMonitorCount(deviceId, count - 1);
}
}, 20 - count * 5, TimeUnit.SECONDS);
}
@Override
public DeviceIotVO setMusic(DeviceVO device, String music, String reason, boolean requiredIot) {
ServiceUtil.assertion(device == null, "设备不存在");
@ -467,14 +457,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
log.info("设备{}更新太频繁,跳过本次更新", device.getMac());
}
// 创建定位日志
if (DeviceUtil.validLocation(device.getLongitude(), device.getLatitude())) {
LocationLog locationLog = locationLogConverter.toPo(device);
if (locationLog != null) {
redisCache.rightPush(CacheConstants.LOCATION_LOG_QUEUE, locationLog);
}
}
return 1;
}
}

View File

@ -1,9 +1,12 @@
package com.ruoyi.bst.device.service.impl;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.springframework.beans.factory.annotation.Autowired;
@ -24,6 +27,7 @@ import com.ruoyi.bst.device.service.DeviceValidator;
import com.ruoyi.bst.device.utils.DeviceUtil;
import com.ruoyi.bst.model.service.ModelValidator;
import com.ruoyi.bst.orderDevice.domain.enums.OrderDeviceStatus;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.utils.DateUtils;
@ -62,6 +66,9 @@ public class DeviceServiceImpl implements DeviceService
@Autowired
private DeviceValidator deviceValidator;
@Autowired
private RedisCache redisCache;
/**
* 查询设备
*
@ -483,9 +490,8 @@ public class DeviceServiceImpl implements DeviceService
if (DeviceOnlineStatus.ONLINE.getStatus().equals(onlineStatus)) {
data.setLastTime(LocalDateTime.now());
}
DeviceQuery query = new DeviceQuery();
query.setEqMac(mac);
return deviceMapper.updateByQuerySimple(data, query);
data.setMac(mac);
return deviceIotService.updateIot(data);
}
@Override
@ -619,4 +625,59 @@ public class DeviceServiceImpl implements DeviceService
return deviceMapper.updateByQuerySimple(data, query);
}
/**
* 批量更新设备IOT数据
*
* @param deviceList 设备列表
* @return 更新成功的记录数
*/
@Override
public int batchUpdateIot(List<Device> deviceList) {
if (CollectionUtils.isEmpty(deviceList)) {
return 0;
}
// 按相同字段分组提高更新效率
Map<String, List<Device>> groupMap = new HashMap<>();
for (Device device : deviceList) {
String key = getUpdateKey(device);
groupMap.computeIfAbsent(key, k -> new ArrayList<>()).add(device);
}
int total = 0;
// 分组批量更新
for (List<Device> group : groupMap.values()) {
// 分批处理每批500条
int batchSize = 500;
for (int i = 0; i < group.size(); i += batchSize) {
int endIndex = Math.min(i + batchSize, group.size());
List<Device> batch = group.subList(i, endIndex);
total += deviceMapper.batchUpdateIot(batch);
}
}
return total;
}
/**
* 获取设备更新字段的key
* 相同字段的设备会被分到同一组进行更新
*/
private String getUpdateKey(Device device) {
StringBuilder key = new StringBuilder();
key.append(device.getVoltage() != null ? "1" : "0")
.append(device.getSignalStrength() != null ? "1" : "0")
.append(device.getQuality() != null ? "1" : "0")
.append(device.getSatellites() != null ? "1" : "0")
.append(device.getIotStatus() != null ? "1" : "0")
.append(device.getLongitude() != null ? "1" : "0")
.append(device.getLatitude() != null ? "1" : "0")
.append(device.getRemainingPower() != null ? "1" : "0")
.append(device.getLastTime() != null ? "1" : "0")
.append(device.getLastLocationTime() != null ? "1" : "0")
.append(device.getOnlineStatus() != null ? "1" : "0")
.append(device.getLastOnlineTime() != null ? "1" : "0")
.append(device.getSoftwareVersion() != null ? "1" : "0");
return key.toString();
}
}

View File

@ -33,7 +33,10 @@ public class OrderEndDTO implements LogBizParam {
@ApiModelProperty("是否必须IOT成功")
private Boolean requiredIot;
@ApiModelProperty("是否需要调度费")
private Boolean needDispatchFee;
@Override
public Object logBizId() {
return orderId;

View File

@ -432,7 +432,8 @@ public class OrderServiceImpl implements OrderService {
// 订单状态
this.setOrderStatus(order, returnType);
// 订单费用
this.setOrderFee(order, area, inParkingVO);
boolean needDispatchFee = dto.getNeedDispatchFee() != null && dto.getNeedDispatchFee();
this.setOrderFee(order, area, inParkingVO, needDispatchFee);
Integer result = transactionTemplate.execute(status -> {
// 更新订单数据
@ -547,8 +548,8 @@ public class OrderServiceImpl implements OrderService {
}
// 设置订单费用
private void setOrderFee(OrderVO order, AreaVO area, OrderInParkingVO inParkingVO) {
OrderFeeVO orderFee = OrderUtil.calcOrderFee(order, area, inParkingVO, order.getEndTime());
private void setOrderFee(OrderVO order, AreaVO area, OrderInParkingVO inParkingVO, boolean needDispatchFee) {
OrderFeeVO orderFee = OrderUtil.calcOrderFee(order, area, inParkingVO, order.getEndTime(), needDispatchFee);
order.setManageFee(orderFee.getManageFee());
order.setDispatchFee(orderFee.getDispatchFee());
order.setRidingFee(orderFee.getRidingFee());
@ -677,7 +678,7 @@ public class OrderServiceImpl implements OrderService {
}
// 计算金额
return OrderUtil.calcOrderFee(order, area, inParkingVO, LocalDateTime.now());
return OrderUtil.calcOrderFee(order, area, inParkingVO, LocalDateTime.now(), true);
}
@Override

View File

@ -55,9 +55,10 @@ public class OrderUtil {
* @param area 运营区
* @param inParkingVO 还车点
* @param endTime 结束时间
* @param needDispatchFee 是否需要调度费
* @return 结果
*/
public static OrderFeeVO calcOrderFee(OrderVO order, AreaVO area, OrderInParkingVO inParkingVO, LocalDateTime endTime) {
public static OrderFeeVO calcOrderFee(OrderVO order, AreaVO area, OrderInParkingVO inParkingVO, LocalDateTime endTime, boolean needDispatchFee) {
OrderFeeVO vo = new OrderFeeVO();
// 骑行费
@ -80,22 +81,24 @@ public class OrderUtil {
}
}
// 运营区外调度费
if (!inParkingVO.getInArea()) {
BigDecimal manageFee = area.getVehicleManagementFee();
if (manageFee == null) {
manageFee = BigDecimal.ZERO;
// 若需要调度费则计算调度费
if (needDispatchFee) {
// 运营区外调度费
if (!inParkingVO.getInArea()) {
BigDecimal manageFee = area.getVehicleManagementFee();
if (manageFee == null) {
manageFee = BigDecimal.ZERO;
}
vo.setManageFee(manageFee);
}
vo.setManageFee(manageFee);
}
// 停车点外调度费
else if (!inParkingVO.getInParking()) {
BigDecimal dispatchFee = area.getDispatchFee();
if (dispatchFee == null) {
dispatchFee = BigDecimal.ZERO;
// 停车点外调度费
else if (!inParkingVO.getInParking()) {
BigDecimal dispatchFee = area.getDispatchFee();
if (dispatchFee == null) {
dispatchFee = BigDecimal.ZERO;
}
vo.setDispatchFee(dispatchFee);
}
vo.setDispatchFee(dispatchFee);
}
// 总费用

View File

@ -39,30 +39,30 @@ public interface IotService {
/**
* 开锁
* @param device 设备
* @param sub 上报频率
* @param reason 原因
* @return 结果
* @param device
* @param sub
* @param reason
* @return
*/
CommandResponse unlock(IotDevice device, int sub, String reason);
CommandResponse unlock(IotDevice device, int sub, String reason, int tryCount);
/**
* 锁车
* @param device 设备
* @param sub 上报频率
* @param reason 原因
* @return 结果
* @param device
* @param sub
* @param reason
* @return
*/
CommandResponse lock(IotDevice device, int sub, String reason);
CommandResponse lock(IotDevice device, int sub, String reason, int tryCount);
/**
* 强制断电
* @param device 设备
* @param sub 上报频率
* @param reason 原因
* @return 结果
* @param device
* @param sub
* @param reason
* @return
*/
CommandResponse qLock(IotDevice device, int sub, String reason);
CommandResponse qLock(IotDevice device, int sub, String reason, int tryCount);
/**
* 播放语音
@ -96,7 +96,15 @@ public interface IotService {
* @param reason
* @return
*/
CommandResponse tempLock(IotDevice device, int sub, String reason);
CommandResponse tempLock(IotDevice device, int sub, String reason, int tryCount);
/**
* 临时锁车
* @param device
* @param sub
* @param reason
* @return
*/
/**
* 设置声音

View File

@ -257,7 +257,23 @@ public class IotServiceImpl implements IotService {
}
private CommandResponse sendCommand(IotDevice device, String command, String reason) {
return sendCommand(device, command, null, reason);
return sendCommand(device, command, reason, 1);
}
private CommandResponse sendCommand(IotDevice device, String command, String reason, int tryCount) {
if (tryCount > 0) {
CommandResponse res = sendCommand(device, command, null, reason);
if (IotUtil.isSuccess(res) || tryCount <= 1) {
return res;
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
log.error("线程休眠异常", e);
}
return sendCommand(device, command, reason, tryCount - 1);
}
return null;
}
// 发送MQTT命令
@ -337,21 +353,21 @@ public class IotServiceImpl implements IotService {
}
@Override
public CommandResponse unlock(IotDevice device, int sub, String reason) {
public CommandResponse unlock(IotDevice device, int sub, String reason, int tryCount) {
String command = IotConstants.COMMAND_UNLOCK + IotConstants.COMMAND_SUB + sub + IotConstants.COMMAND_SEPARATOR;
return sendCommand(device, command, reason);
return sendCommand(device, command, reason, tryCount);
}
@Override
public CommandResponse lock(IotDevice device, int sub, String reason) {
public CommandResponse lock(IotDevice device, int sub, String reason, int tryCount) {
String command = IotConstants.COMMAND_LOCK + IotConstants.COMMAND_SUB + sub + IotConstants.COMMAND_SEPARATOR;
return sendCommand(device, command, reason);
return sendCommand(device, command, reason, tryCount);
}
@Override
public CommandResponse qLock(IotDevice device, int sub, String reason) {
public CommandResponse qLock(IotDevice device, int sub, String reason, int tryCount) {
String command = IotConstants.COMMAND_QLOSE + IotConstants.COMMAND_SUB + sub + IotConstants.COMMAND_SEPARATOR;
return sendCommand(device, command, reason);
return sendCommand(device, command, reason, tryCount);
}
@Override
@ -373,8 +389,8 @@ public class IotServiceImpl implements IotService {
}
@Override
public CommandResponse tempLock(IotDevice device, int sub, String reason) {
return sendCommand(device, IotConstants.COMMAND_LLOSE, reason);
public CommandResponse tempLock(IotDevice device, int sub, String reason, int tryCount) {
return sendCommand(device, IotConstants.COMMAND_LLOSE, reason, tryCount);
}
@Override

View File

@ -2,7 +2,9 @@ package com.ruoyi.task.device;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import com.ruoyi.common.utils.collection.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -10,6 +12,8 @@ import com.ruoyi.bst.device.domain.Device;
import com.ruoyi.bst.device.domain.DeviceQuery;
import com.ruoyi.bst.device.service.DeviceIotService;
import com.ruoyi.bst.device.service.DeviceService;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.iot.service.impl.DeviceOnlineStatus;
import lombok.extern.slf4j.Slf4j;
@ -24,6 +28,9 @@ public class DeviceTask {
@Autowired
private DeviceService deviceService;
@Autowired
private RedisCache redisCache;
// 监控所有设备
public void monitorAll() {
deviceIotService.monitor(new ArrayList<>());
@ -36,12 +43,22 @@ public class DeviceTask {
// 条件在线且最后上报时间小于当前时间 - seconds秒
DeviceQuery query = new DeviceQuery();
query.setOnlineStatus(DeviceOnlineStatus.ONLINE.getStatus());
query.setLastTimeEnd(LocalDateTime.now().plusSeconds(-seconds));
query.setLastTimeEnd(LocalDateTime.now().plusSeconds(-seconds));
Device data = new Device();
data.setOnlineStatus(DeviceOnlineStatus.OFFLINE.getStatus());
int update = deviceService.updateByQuerySimple(data, query);
log.info("更新了{}条离线的设备数据", update);
}
public void refreshIot() {
// 从队列中获取数据
List<Device> deviceList = redisCache.getAndClearCacheList(CacheConstants.DEVICE_UPDATE_IOT_QUEUE);
if (CollectionUtils.isEmptyElement(deviceList)) {
return ;
}
int rows = deviceService.batchUpdateIot(deviceList);
log.info("更新了{}条设备IOT数据", rows);
}
}

View File

@ -113,6 +113,7 @@ public class AppOrderController extends BaseController {
dto.setReturnType(OrderReturnType.NORMAL.getCode());
dto.setEndReason("用户【" + getNickName() + "】手动还车");
dto.setRequiredIot(false);
dto.setNeedDispatchFee(true);
OrderEndVO vo = orderService.endOrder(dto);
if (vo.getDb() > 0) {
return success(vo);

View File

@ -115,6 +115,9 @@ public class OrderController extends BaseController
dto.setReturnType(OrderReturnType.AUXILIARY.getCode());
dto.setEndReason("管理员【" + getNickName() + "】手动还车");
dto.setRequiredIot(false);
if (dto.getNeedDispatchFee() == null) {
dto.setNeedDispatchFee(false);
}
OrderEndVO vo = orderService.endOrder(dto);
if (vo.getDb() > 0) {
return success(vo);