From 33b469cdbce1261624558501180e96be8e14056a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A3=B7=E5=8F=B6?= <14103883+leaf-phos@user.noreply.gitee.com> Date: Fri, 16 May 2025 17:33:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruoyi/common/constant/CacheConstants.java | 5 + .../com/ruoyi/common/utils/MathUtils.java | 2 +- .../service/impl/AreaSubServiceImpl.java | 15 ++- .../service/impl/CommandLogServiceImpl.java | 4 + .../ruoyi/bst/device/mapper/DeviceMapper.java | 7 ++ .../ruoyi/bst/device/mapper/DeviceMapper.xml | 102 ++++++++++++++++++ .../bst/device/service/DeviceService.java | 7 ++ .../service/impl/DeviceIotServiceImpl.java | 72 +++++-------- .../service/impl/DeviceServiceImpl.java | 67 +++++++++++- .../bst/order/domain/dto/OrderEndDTO.java | 5 +- .../order/service/impl/OrderServiceImpl.java | 9 +- .../com/ruoyi/bst/order/utils/OrderUtil.java | 33 +++--- .../com/ruoyi/iot/service/IotService.java | 42 +++++--- .../iot/service/impl/IotServiceImpl.java | 34 ++++-- .../com/ruoyi/task/device/DeviceTask.java | 21 +++- .../com/ruoyi/web/app/AppOrderController.java | 1 + .../com/ruoyi/web/bst/OrderController.java | 3 + 17 files changed, 327 insertions(+), 102 deletions(-) diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java index 4a9f47f..2eba440 100644 --- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java +++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java @@ -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"; } diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MathUtils.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MathUtils.java index 19a6912..26f879d 100644 --- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MathUtils.java +++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/utils/MathUtils.java @@ -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; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java index be21e95..d89f6f3 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java @@ -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 ids) { + public int logicDel(List 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 selectAreaSubByIds(List ids) { if (CollectionUtils.isEmptyElement(ids)) { diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/commandLog/service/impl/CommandLogServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/commandLog/service/impl/CommandLogServiceImpl.java index 0c28a80..b4b328b 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/commandLog/service/impl/CommandLogServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/commandLog/service/impl/CommandLogServiceImpl.java @@ -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() + "(蓝牙)"); diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.java b/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.java index 70fe2de..7d09e5f 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.java @@ -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 list); + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml b/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml index 14acc6d..0187a64 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml @@ -498,4 +498,106 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + update bst_device + + + voltage = case mac + + when #{item.mac} then #{item.voltage} + + else voltage end, + + + signal_strength = case mac + + when #{item.mac} then #{item.signalStrength} + + else signal_strength end, + + + quality = case mac + + when #{item.mac} then #{item.quality} + + else quality end, + + + satellites = case mac + + when #{item.mac} then #{item.satellites} + + else satellites end, + + + iot_status = case mac + + when #{item.mac} then #{item.iotStatus} + + else iot_status end, + + + longitude = case mac + + when #{item.mac} then #{item.longitude} + + else longitude end, + + + latitude = case mac + + when #{item.mac} then #{item.latitude} + + else latitude end, + + + remaining_power = case mac + + when #{item.mac} then #{item.remainingPower} + + else remaining_power end, + + + last_time = case mac + + when #{item.mac} then #{item.lastTime} + + else last_time end, + + + last_location_time = case mac + + when #{item.mac} then #{item.lastLocationTime} + + else last_location_time end, + + + online_status = case mac + + when #{item.mac} then #{item.onlineStatus} + + else online_status end, + + + last_online_time = case mac + + when #{item.mac} then #{item.lastOnlineTime} + + else last_online_time end, + + + software_version = case mac + + when #{item.mac} then #{item.softwareVersion} + + else software_version end, + + + where mac in + + #{item.mac} + + diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/DeviceService.java b/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/DeviceService.java index 44356a7..3d1ff3a 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/DeviceService.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/DeviceService.java @@ -231,4 +231,11 @@ public interface DeviceService * @return */ public int updateByQuerySimple(Device data, DeviceQuery query); + + /** + * 批量更新IOT数据 + * @param list + * @return + */ + public int batchUpdateIot(List list); } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceIotServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceIotServiceImpl.java index b43fe00..aaee3c3 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceIotServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceIotServiceImpl.java @@ -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; } } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceServiceImpl.java index 3226d0f..37fd305 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/service/impl/DeviceServiceImpl.java @@ -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 deviceList) { + if (CollectionUtils.isEmpty(deviceList)) { + return 0; + } + + // 按相同字段分组,提高更新效率 + Map> groupMap = new HashMap<>(); + for (Device device : deviceList) { + String key = getUpdateKey(device); + groupMap.computeIfAbsent(key, k -> new ArrayList<>()).add(device); + } + + int total = 0; + // 分组批量更新 + for (List 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 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(); + } + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderEndDTO.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderEndDTO.java index 06e411f..df6f186 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderEndDTO.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderEndDTO.java @@ -33,7 +33,10 @@ public class OrderEndDTO implements LogBizParam { @ApiModelProperty("是否必须IOT成功") private Boolean requiredIot; - + + @ApiModelProperty("是否需要调度费") + private Boolean needDispatchFee; + @Override public Object logBizId() { return orderId; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java index 647b686..2d9f46f 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java @@ -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 diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java index 87bce18..6f19b62 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java @@ -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); } // 总费用 diff --git a/ruoyi-service/src/main/java/com/ruoyi/iot/service/IotService.java b/ruoyi-service/src/main/java/com/ruoyi/iot/service/IotService.java index 6fbb813..198f3d4 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/iot/service/IotService.java +++ b/ruoyi-service/src/main/java/com/ruoyi/iot/service/IotService.java @@ -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 + */ /** * 设置声音 diff --git a/ruoyi-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java index 3e92e5e..b6c5872 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java @@ -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 diff --git a/ruoyi-web/src/main/java/com/ruoyi/task/device/DeviceTask.java b/ruoyi-web/src/main/java/com/ruoyi/task/device/DeviceTask.java index 7c1a37f..c4540a6 100644 --- a/ruoyi-web/src/main/java/com/ruoyi/task/device/DeviceTask.java +++ b/ruoyi-web/src/main/java/com/ruoyi/task/device/DeviceTask.java @@ -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 deviceList = redisCache.getAndClearCacheList(CacheConstants.DEVICE_UPDATE_IOT_QUEUE); + if (CollectionUtils.isEmptyElement(deviceList)) { + return ; + } + int rows = deviceService.batchUpdateIot(deviceList); + log.info("更新了{}条设备IOT数据", rows); + } + } diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java b/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java index 0c9b89a..9632388 100644 --- a/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java +++ b/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java @@ -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); diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java b/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java index 8c2985e..aec8d79 100644 --- a/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java +++ b/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java @@ -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);