设备监控

This commit is contained in:
磷叶 2024-12-30 14:50:25 +08:00
parent 184e651fb5
commit 049b8470ad
10 changed files with 117 additions and 194 deletions

View File

@ -4,6 +4,7 @@ import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;

View File

@ -306,11 +306,6 @@ public interface DeviceService
*/
int resetEle(DeviceVO device, boolean required, String reason);
/**
* 归零电量
*/
int resetEle(Long deviceId, boolean required, String reason);
/**
* 添加电量
*/

View File

@ -401,8 +401,8 @@ public class DeviceServiceImpl implements DeviceService
// 物联网设备归零
try {
CommandResponse res = iotService.setTime(device, 0L, reason);
ServiceUtil.assertion(res == null, "设备归零失败,返回值为空");
ServiceUtil.assertion(!res.isSuccess(), "设备归零失败,请检查设备是否在线或联系管理员");
ServiceUtil.assertion(res == null, "设备%s归零失败,返回值为空", device.getDeviceNo());
ServiceUtil.assertion(!res.isSuccess(), "设备%s归零失败,请检查设备是否在线或联系管理员", device.getDeviceNo());
} catch (Exception e) {
log.warn("设备归零失败:{}, {}, {}", device.getDeviceId(), device.getDeviceNo(), e.getMessage());
if (required) {
@ -490,14 +490,6 @@ public class DeviceServiceImpl implements DeviceService
return deviceMapper.updateSmDevice(data);
}
@Override
public int resetEle(Long deviceId, boolean required, String reason) {
// 获取设备信息
DeviceVO device = selectById(deviceId);
this.pullDeviceInfo(device, IotConstants.ONLINE_TYPE_GET);
return resetEle(device, required, reason);
}
@Override
public boolean addEle(Long deviceId, BigDecimal ele, String reason, boolean requiredIot) {
DeviceVO device = selectById(deviceId);
@ -829,14 +821,7 @@ public class DeviceServiceImpl implements DeviceService
}
// 关闭设备未结束的订单
TransactionBillQuery query = new TransactionBillQuery();
query.setType(TransactionBillType.RECHARGE.getType());
query.setStatusList(TransactionBillStatus.canClose());
query.setDeviceId(deviceId);
query.setIsFinished(false);
List<TransactionBillVO> billList = transactionBillService.selectSmTransactionBillList(query);
int closeCount = transactionBillService.batchCloseBillByDevice(billList, false, device, null);
ServiceUtil.assertion(closeCount != billList.size(), "关闭订单失败:closeCount =" + closeCount);
this.closeNotFinishedBill(device, device.getTotalElectriQuantity());
}
int i = deviceMapper.logicDel(deviceIds);
@ -1042,7 +1027,7 @@ public class DeviceServiceImpl implements DeviceService
data.setStatus(device.getStatus());
data.setOnlineStatus(device.getOnlineStatus());
data.setLastOnlineTime(device.getLastOnlineTime());
return deviceMapper.updateSmDevice(device);
return deviceMapper.updateSmDevice(data);
}
/**
@ -1155,34 +1140,50 @@ public class DeviceServiceImpl implements DeviceService
pullDeviceInfo(device, IotConstants.ONLINE_TYPE_GET);
Integer result = transactionTemplate.execute(status -> {
// 修改设备信息
Device data = new Device();
data.setDeviceId(deviceId);
data.setStatus(DeviceStatus.NORMAL.getStatus());
if (withTime) {
data.setExpireTime(LocalDateTime.now());
}
if (withEle) {
data.setSurplusEle(BigDecimal.ZERO);
data.setExpireEle(device.getTotalElectriQuantity());
}
int update = deviceMapper.updateSmDevice(data);
ServiceUtil.assertion(update != 1, "更新设备%s信息失败", device.getDeviceNo());
// 关闭未完成订单
this.closeNotFinishedBill(device, totalEle);
// 修改设备信息
if (withTime) {
int timeUpdate = this.resetUpdateDbTime(deviceId);
ServiceUtil.assertion(timeUpdate != 1, "修改设备时间失败");
}
if (withEle) {
int eleUpdate = this.resetUpdateDbEle(deviceId, device.getTotalElectriQuantity());
ServiceUtil.assertion(eleUpdate != 1, "修改设备电量失败");
}
// 发送命令
if (withTime) {
this.resetTime(device, requiredIot, reason);
}
// this.resetTime(device, false, reason); // 重置时长
if (withEle) {
CommandResponse res = iotService.setTime(device, 0L, reason);
if (requiredIot) {
ServiceUtil.assertion(res == null, "归零电量失败,返回值为空");
ServiceUtil.assertion(!res.isSuccess(), "归零电量失败,请检查设备是否在线或联系管理员");
}
}
if (withTime && withEle) {
try {
Thread.sleep(5000);
} catch (Exception e) {
log.error("设备归零等待时间异常:{}", e.getMessage());
throw new ServiceException(e.getMessage());
}
}
if (withEle) {
// this.resetEle(device, false, reason); // 重置电量
this.resetEle(device, requiredIot, reason);
CommandResponse res = iotService.setEle(device, BigDecimal.ZERO, reason);
if (requiredIot) {
ServiceUtil.assertion(res == null, "归零电量失败,返回值为空");
ServiceUtil.assertion(!res.isSuccess(), "归零电量失败,请检查设备是否在线或联系管理员");
}
}
return 1;
@ -1212,15 +1213,11 @@ public class DeviceServiceImpl implements DeviceService
query.setDeviceId(device.getDeviceId());
query.setIsFinished(false); // 未结束的订单都会被关闭
List<TransactionBillVO> billList = transactionBillService.selectSmTransactionBillList(query);
int closeCount = 0;
try {
closeCount = transactionBillService.batchCloseBillByDevice(billList, false, device, totalEle);
ServiceUtil.assertion(closeCount != billList.size(), "关闭订单失败:closeCount =" + closeCount);
} catch (Exception e) {
log.error("关闭订单失败: {}", e.getMessage());
if (CollectionUtils.isEmptyElement(billList)) {
return 0;
}
return closeCount;
return transactionBillService.batchCloseBillByDevice(billList, device, totalEle);
}
@Override
@ -1335,24 +1332,22 @@ public class DeviceServiceImpl implements DeviceService
// 一般情况下物联网设备的值会大于或等于当前数据库的值
long deviceSeconds = device.getRemainTime() == null ? 0 : device.getRemainTime().longValue();
if (device.getSurplusSecondsDb() > deviceSeconds) {
this.syncTime(device.getDeviceId(), LocalDateTime.now(), "设备监控-同步ch时长");
this.syncTime(device.getDeviceId(), LocalDateTime.now(), "设备监控-同步时长");
}
if (device.getSurplusEleDb().compareTo(device.getSurplusEle()) > 0) {
this.syncEle(device.getDeviceId(), "设备监控-同步电量");
}
// 若当前设备数据库的时长或者电量<=0且在这之后用户没有发open命令则执行一次同步关闭
// 若当前设备数据库的时长并且电量<=0且在这之后用户没有发open命令则执行一次同步关闭
boolean hasOpen = DeviceUserOperaType.OPEN.getType().equals(device.getUserOperaType()); // 是否开启过
LocalDateTime lastOperaTime = device.getUserOperaTime(); // 上次开启的时间
BigDecimal lastOperaEle = device.getUserOperaEle(); // 上次开启的总用电量
boolean hasOpenAfterExpireTime = hasOpen && lastOperaTime != null && lastOperaTime.isAfter(device.getExpireTime()); // 是否在时间结束后开启
if (device.getSurplusSecondsDb() <= 0 && !hasOpenAfterExpireTime) {
this.switchDevice(device, DevicePowerStatus.OFF, "设备监控-发现异常未关闭设备");
}
boolean hasTime = device.getSurplusSecondsDb() > 0; // 剩余时间
boolean hasOpenAfterExpireEle = hasOpen && lastOperaEle != null && lastOperaEle.compareTo(device.getExpireEle()) > 0; // 是否在结束电量后开启
if (device.getSurplusEle().compareTo(device.getSurplusEleDb()) <= 0 && !hasOpenAfterExpireEle) {
boolean hasEle = device.getSurplusEleDb().compareTo(BigDecimal.ZERO) > 0; // 剩余电量
if (!hasTime && !hasEle && !hasOpenAfterExpireTime && !hasOpenAfterExpireEle) {
this.switchDevice(device, DevicePowerStatus.OFF, "设备监控-发现异常未关闭设备");
}
},0, TimeUnit.SECONDS);

View File

@ -53,4 +53,10 @@ public class RealName extends BaseEntity
@ApiModelProperty("认证类型")
private String type;
@ApiModelProperty("身份证正面")
private String idCardFront;
@ApiModelProperty("身份证背面")
private String idCardBack;
}

View File

@ -17,6 +17,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
srn.score,
srn.face_image,
srn.type,
srn.id_card_front,
srn.id_card_back,
su.user_name as user_name
from ss_real_name srn
left join sm_user su on su.user_id = srn.user_id
@ -68,6 +70,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="score != null">score,</if>
<if test="faceImage != null">face_image,</if>
<if test="type != null and type != ''">type,</if>
<if test="idCardFront!= null">id_card_front,</if>
<if test="idCardBack!= null">id_card_back,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userId != null">#{userId},</if>
@ -78,6 +82,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="score != null">#{score},</if>
<if test="faceImage != null">#{faceImage},</if>
<if test="type != null and type != ''">#{type},</if>
<if test="idCardFront!= null">#{idCardFront},</if>
<if test="idCardBack!= null">#{idCardBack},</if>
</trim>
</insert>
@ -98,6 +104,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="data.score != null">score = #{data.score},</if>
<if test="data.faceImage != null">face_image = #{data.faceImage},</if>
<if test="data.type != null and data.type != ''">type = #{data.type},</if>
<if test="data.idCardFront!= null">id_card_front = #{data.idCardFront},</if>
<if test="data.idCardBack!= null">id_card_back = #{data.idCardBack},</if>
</sql>
<delete id="deleteRealNameById" parameterType="Long">

View File

@ -7,7 +7,6 @@ import com.ruoyi.ss.payBill.domain.vo.DoPayVO;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.bo.*;
import com.ruoyi.ss.transactionBill.domain.dto.EndUseDTO;
import com.ruoyi.ss.transactionBill.domain.dto.RechargePayBO;
import com.ruoyi.ss.transactionBill.domain.vo.*;
import com.ruoyi.ss.transactionBill.domain.dto.BillRefundDTO;
@ -228,7 +227,7 @@ public interface TransactionBillService
/**
* 根据设备ID批量结束订单
*/
int batchCloseBillByDevice(List<TransactionBillVO> billList, boolean withDevice, DeviceVO device, BigDecimal totalEle);
int batchCloseBillByDevice(List<TransactionBillVO> billList, DeviceVO device, BigDecimal totalEle);
/**
* 获取用户提现手续费信息
@ -281,12 +280,7 @@ public interface TransactionBillService
/**
* 结束使用订单
*/
EndUseVO endUse(EndUseBO bo, boolean withDevice);
/**
* 结束使用订单
*/
EndUseVO endUse(EndUseDTO dto, boolean withDevice);
int endUse(EndUseBO bo);
/**
* 查询所有关于金额的总和

View File

@ -997,9 +997,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
}
}
public EndUseVO endTimingUse(EndUseBO bo, boolean withDevice) {
private int endTimingUse(EndUseBO bo) {
if (bo == null) {
return EndUseVO.fail();
return 0;
}
TransactionBillVO order = bo.getOrder();
DeviceVO device = bo.getDevice();
@ -1033,36 +1033,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return update;
});
// 尝试关闭设备
if (result != null && result == 1) {
try {
transactionTemplate.execute(status -> {
// 记录设备关闭状态
int update = this.updateCloseStatus(order.getBillId(), RechargeCloseStatus.SUCCESS, "成功");
ServiceUtil.assertion(update != 1, "记录设备关闭状态失败,请刷新后重试");
String reason = "分时段订单结束使用:" + order.getBillNo();
if (withDevice) {
if (SuitFeeType.TIMING_COUNT.getType().equals(order.getSuitFeeType())) {
deviceService.resetEle(device, false, reason);
} else if(SuitFeeType.TIMING_TIME.getType().equals(order.getSuitFeeType())){
deviceService.resetTime(device, false, reason);
}
int switchDevice = deviceService.switchDevice(device, DevicePowerStatus.OFF, reason);
ServiceUtil.assertion(switchDevice != 1, "操作设备失败");
}
return update;
});
} catch (Exception e) {
log.error("尝试关闭设备失败: {}", e.getMessage());
this.updateCloseStatus(order.getBillId(), RechargeCloseStatus.FAIL, e.getMessage());
return EndUseVO.toResult(result, false, e.getMessage());
}
}
return EndUseVO.toResult(result, true, null);
return result == null ? 0 : result;
}
private BigDecimal calcTotalEle(DeviceVO device, BigDecimal totalEle) {
@ -1093,9 +1064,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return totalAmount;
}
public EndUseVO endSmartUse(EndUseBO bo, boolean withDevice) {
private int endSmartUse(EndUseBO bo) {
if (bo == null) {
return EndUseVO.fail();
return 0;
}
TransactionBillVO order = bo.getOrder();
DeviceVO device = bo.getDevice();
@ -1145,36 +1116,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
ServiceUtil.assertion(refund != 1, "申请退款失败");
}, 10, TimeUnit.SECONDS);
}
// 清零设备
try {
transactionTemplate.execute(status -> {
// 记录设备关闭状态成功
int update = this.updateCloseStatus(order.getBillId(), RechargeCloseStatus.SUCCESS, "成功");
ServiceUtil.assertion(update != 1, "更新设备关闭状态失败");
// 尝试设备清零时长电量
String reason = String.format("智能订单结束使用: %s", order.getBillNo());
if (withDevice) {
if (SuitFeeType.TIME.getType().equals(order.getSuitFeeType())) {
deviceService.resetTime(device, false, reason);
} else if (SuitFeeType.COUNT.getType().equals(order.getSuitFeeType())) {
deviceService.resetEle(device, false, reason);
}
}
return update;
});
} catch (Exception e) {
log.warn("设备归零失败: {}", e.getMessage());
// 记录设备关闭状态
this.updateCloseStatus(order.getBillId(), RechargeCloseStatus.FAIL, e.getMessage());
return EndUseVO.toResult(result, false, e.getMessage());
}
}
return EndUseVO.toResult(result, true, null);
return result == null ? 0 : result;
}
private int updateCloseStatus(Long billId, RechargeCloseStatus status, String msg) {
@ -1219,9 +1163,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return transactionBillMapper.selectSumOfMoney(query);
}
public EndUseVO endUseSingle(EndUseBO bo, boolean withDevice) {
private int endUseSingle(EndUseBO bo) {
if (bo == null) {
return EndUseVO.fail();
return 0;
}
TransactionBillVO order = bo.getOrder();
DeviceVO device = bo.getDevice();
@ -1244,46 +1188,13 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
query.setBillId(order.getBillId());
query.setStatus(TransactionBillStatus.SUCCESS.getStatus());
query.setIsFinished(false);
// if (SuitFeeType.TIME.getType().equals(order.getSuitFeeType())) {
// query.setStartSuitEndTime(endTime); // 计时的话需要结束时间在这之后的订单
// } else if (SuitFeeType.COUNT.getType().equals(order.getSuitFeeType())) {
// query.setStartSuitEndEle(totalEle); // 计量的话需要结束电量比这个大的订单
// }
int update = this.updateByQuery(data, query);
ServiceUtil.assertion(update != 1, "修改订单信息失败,请重试:" + order.getBillNo());
return update;
});
// 尝试清零设备
if (result != null && result == 1) {
try {
transactionTemplate.execute(status -> {
// 记录设备关闭状态成功
int update = this.updateCloseStatus(order.getBillId(), RechargeCloseStatus.SUCCESS, "成功");
ServiceUtil.assertion(update != 1, "更新设备关闭状态失败");
// 尝试设备清零时长电量
String reason = String.format("单次订单结束使用: %s", order.getBillNo());
if (withDevice) {
if (SuitFeeType.COUNT.getType().equals(order.getSuitFeeType())) {
deviceService.resetEle(device, false, reason);
} else if(SuitFeeType.TIME.getType().equals(order.getSuitFeeType())){
deviceService.resetTime(device, false, reason);
}
}
return update;
});
} catch (Exception e) {
log.error("尝试清零设备失败: {}", e.getMessage());
// 记录设备关闭状态
this.updateCloseStatus(order.getBillId(), RechargeCloseStatus.FAIL, e.getMessage());
return EndUseVO.toResult(result, false, e.getMessage());
}
}
return EndUseVO.toResult(result, true, null);
return result == null ? 0 : result;
}
/**
@ -1836,7 +1747,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
}
@Override
public int batchCloseBillByDevice(List<TransactionBillVO> billList, boolean withDevice, DeviceVO device, BigDecimal totalEle) {
public int batchCloseBillByDevice(List<TransactionBillVO> billList, DeviceVO device, BigDecimal totalEle) {
if (CollectionUtils.isEmptyElement(billList)) {
return 0;
}
@ -1845,21 +1756,18 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
bo.setTotalEle(totalEle);
if (CollectionUtils.isNotEmptyElement(billList)) {
Integer result = transactionTemplate.execute(status -> {
int sum = 0;
// 关闭订单智能订单需要退款
for (TransactionBillVO bill : billList) {
// 关闭订单
int sum = 0;
for (TransactionBillVO bill : billList) {
Integer result = transactionTemplate.execute(status -> {
bo.setOrder(bill);
EndUseVO end = this.endUse(bo, withDevice);
ServiceUtil.assertion(end.getResult() != 1, "关闭订单失败:" + bill.getBillNo());
sum += end.getResult();
}
return sum;
});
return result == null ? 0 : result;
int end = this.endUse(bo);
ServiceUtil.assertion(end != 1, "关闭订单失败:" + bill.getBillNo());
return end;
});
sum += (result == null ? 0 : result);
}
return sum;
}
return 0;
@ -1867,9 +1775,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
// 结束使用订单
@Override
public EndUseVO endUse(EndUseBO bo, boolean withDevice) {
public int endUse(EndUseBO bo) {
if (bo == null) {
return EndUseVO.fail();
return 0;
}
TransactionBillVO bill = bo.getOrder();
@ -1877,25 +1785,19 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
if (SuitFeeMode.SMART.getMode().equals(bill.getSuitFeeMode())) {
// 单次智能
if (SuitFeeType.singleList().contains(bill.getSuitFeeType())) {
return this.endSmartUse(bo, withDevice);
return this.endSmartUse(bo);
}
// 分时段智能
else if (SuitFeeType.timingList().contains(bill.getSuitFeeType())){
return this.endTimingUse(bo, withDevice);
return this.endTimingUse(bo);
}
}
// 单次订单
else if (SuitFeeMode.SINGLE.getMode().equals(bill.getSuitFeeMode())) {
return this.endUseSingle(bo, withDevice);
return this.endUseSingle(bo);
}
return EndUseVO.fail();
}
@Override
public EndUseVO endUse(EndUseDTO dto, boolean withDevice) {
EndUseBO bo = transactionBillConverter.toEndUseBO(dto);
return this.endUse(bo, withDevice);
return 0;
}
@Override

View File

@ -5,6 +5,7 @@ import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.iot.domain.IotDeviceInfo;
import com.ruoyi.iot.service.IotService;
import com.ruoyi.ss.device.domain.enums.DeviceOnlineStatus;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.suit.domain.enums.SuitFeeType;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.dto.EndUseDTO;
@ -40,6 +41,9 @@ public class BillMonitorTask {
@Autowired
private IotService iotService;
@Autowired
private DeviceService deviceService;
/**
* 关闭低功率的订单
*/
@ -77,12 +81,10 @@ public class BillMonitorTask {
}
IotDeviceInfo deviceInfo = iotService.getDeviceInfo(bill);
// 判断是否低功率若低于指定功率则关闭订单
// 判断是否低功率若低于指定功率则关闭订单清零设备
if (deviceInfo != null && deviceInfo.getP() != null && deviceInfo.getP().compareTo(bill.getSuitLowPower()) < 0) {
EndUseDTO dto = new EndUseDTO();
dto.setBillId(bill.getBillId());
dto.setTotalEle(deviceInfo.getW());
transactionBillService.endUse(dto, true);
String reason = String.format("低功率订单%s自动关闭", bill.getBillNo());
deviceService.resetWithBill(bill.getDeviceId(), true, deviceInfo.getW(), reason, false, true);
}
} catch (Exception e) {
log.warn("关闭低功率订单{}出错:{}", bill.getBillNo(), e.getMessage());

View File

@ -175,7 +175,8 @@ public class AppDeviceController extends BaseController {
if (!deviceValidator.canOpera(deviceId, getUserId()) ) {
return error("您无权操作此设备");
}
return toAjax(smDeviceService.resetWithBill(deviceId, true, null, "商户设备归零:id=" + deviceId, true, true));
String reason = String.format("商户设备归零:id=%s", deviceId);
return toAjax(smDeviceService.resetWithBill(deviceId, true, null, reason, true, true));
}
@ApiOperation("获取设备用电量分析")

View File

@ -5,6 +5,8 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.suit.domain.enums.SuitFeeType;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.dto.EndUseDTO;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
@ -51,6 +53,9 @@ public class SmTransactionBillController extends BaseController
@Autowired
private TransactionAssembler transactionAssembler;
@Autowired
private DeviceService deviceService;
/**
* 查询充值记录列表
*/
@ -164,7 +169,21 @@ public class SmTransactionBillController extends BaseController
@Log(title = "结束订单", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('system:bill:close')")
public AjaxResult close(@RequestBody @Validated EndUseDTO dto) {
return success(transactionBillService.endUse(transactionBillConverter.toEndUseBO(dto), true));
TransactionBillVO order = transactionBillService.selectSmTransactionBillByBillId(dto.getBillId());
if (order == null) {
return error("订单不存在");
}
String reason = "后台关闭订单:" + order.getBillNo();
if (SuitFeeType.rechargeTimeList().contains(order.getSuitFeeType())) {
int i = deviceService.resetWithBill(order.getDeviceId(), false, null, reason, true, false);
return toAjax(i);
} else if (SuitFeeType.rechargeCountList().contains(order.getSuitFeeType())) {
int i = deviceService.resetWithBill(order.getDeviceId(), false, null, reason, false, true);
return toAjax(i);
}
return error("暂不支持该订单类型");
}
// 修复订单数据