This commit is contained in:
磷叶 2024-12-25 14:08:51 +08:00
parent 4459deed86
commit 35faad32fa
10 changed files with 162 additions and 98 deletions

View File

@ -23,6 +23,7 @@ public class DeviceBO extends Device {
bo.setCustomPicture(getCustomPicture());
bo.setModelId(getModelId());
bo.setMac(getMac());
bo.setMac2(getMac2());
bo.setDeviceNo(getDeviceNo());
bo.setDeviceName(getDeviceName());
bo.setServiceRate(getServiceRate());

View File

@ -121,4 +121,15 @@ public class DeviceVO extends Device implements IotDevice {
public String getProductId() {
return getModelProductId();
}
// 获取数据库剩余电量
public BigDecimal getSurplusEleDb() {
if (getExpireEle() == null) {
return BigDecimal.ZERO;
}
if (getTotalElectriQuantity() == null) {
return getExpireEle();
}
return getExpireEle().subtract(getTotalElectriQuantity());
}
}

View File

@ -1,11 +1,11 @@
package com.ruoyi.ss.device.service;
import com.ruoyi.iot.domain.response.CommandResponse;
import com.ruoyi.ss.device.domain.*;
import com.ruoyi.ss.device.domain.dto.DeviceBatchUpdateModelDTO;
import com.ruoyi.ss.device.domain.dto.DeviceRegisterDTO;
import com.ruoyi.ss.device.domain.dto.DeviceWifiDTO;
import com.ruoyi.ss.device.domain.enums.DevicePowerStatus;
import com.ruoyi.ss.device.domain.vo.DeviceIotResultVO;
import com.ruoyi.ss.device.domain.vo.DeviceMacSnVO;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
@ -85,9 +85,9 @@ public interface DeviceService
* @param reason
* @param requiredIot
*/
DeviceIotResultVO addTime(Long deviceId, long seconds, String reason, boolean requiredIot);
boolean addTime(Long deviceId, long seconds, String reason, boolean requiredIot);
DeviceIotResultVO addTime(DeviceVO device, long seconds, String reason, boolean requiredIot);
boolean addTime(DeviceVO device, long seconds, String reason, boolean requiredIot);
/**
* 逻辑删除
@ -314,12 +314,12 @@ public interface DeviceService
/**
* 添加电量
*/
DeviceIotResultVO addEle(Long deviceId, BigDecimal amount, String reason, boolean requiredIot);
boolean addEle(Long deviceId, BigDecimal amount, String reason, boolean requiredIot);
/**
* 添加电量
*/
DeviceIotResultVO addEle(DeviceVO device, BigDecimal amount, String reason, boolean requiredIot);
boolean addEle(DeviceVO device, BigDecimal amount, String reason, boolean requiredIot);
int updateLastRecoverTime(Long deviceId, Long lastRecoverTime);
@ -410,4 +410,28 @@ public interface DeviceService
*/
int reboot(DeviceVO device, String reason);
/**
* 增加数据库设备时长
* @param deviceId 设备ID
* @param seconds
* @return
*/
int addTimeDb(Long deviceId, long seconds);
/**
* 增加电量
* @param deviceId 设备ID
* @param amount
*/
int addEleDb(Long deviceId, BigDecimal amount);
/**
* 同步时间
*/
CommandResponse syncTime(Long deviceId, LocalDateTime now, String reason);
/**
* 同步电量
*/
CommandResponse syncEle(Long deviceId, String reason);
}

View File

@ -1,6 +1,5 @@
package com.ruoyi.ss.device.service.impl;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.IotConstants;
import com.ruoyi.common.core.redis.RedisLock;
@ -14,8 +13,6 @@ import com.ruoyi.iot.domain.IotDeviceInfo;
import com.ruoyi.iot.domain.response.CommandResponse;
import com.ruoyi.iot.enums.IotHttpStatus;
import com.ruoyi.iot.service.IotService;
import com.ruoyi.ss.commandLog.domain.CommandLogQuery;
import com.ruoyi.ss.commandLog.domain.CommandLogVO;
import com.ruoyi.ss.commandLog.service.ICommandLogService;
import com.ruoyi.ss.device.domain.Device;
import com.ruoyi.ss.device.domain.DeviceBO;
@ -28,7 +25,6 @@ import com.ruoyi.ss.device.domain.enums.DeviceOnlineStatus;
import com.ruoyi.ss.device.domain.enums.DevicePowerStatus;
import com.ruoyi.ss.device.domain.enums.DeviceServiceMode;
import com.ruoyi.ss.device.domain.enums.DeviceStatus;
import com.ruoyi.ss.device.domain.vo.DeviceIotResultVO;
import com.ruoyi.ss.device.domain.vo.DeviceMacSnVO;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.mapper.DeviceMapper;
@ -505,38 +501,30 @@ public class DeviceServiceImpl implements DeviceService
}
@Override
public DeviceIotResultVO addEle(Long deviceId, BigDecimal ele, String reason, boolean requiredIot) {
public boolean addEle(Long deviceId, BigDecimal ele, String reason, boolean requiredIot) {
DeviceVO device = selectById(deviceId);
return this.addEle(device, ele, reason, requiredIot);
}
@Override
public DeviceIotResultVO addEle(DeviceVO device, BigDecimal amount, String reason, boolean requiredIot) {
public boolean addEle(DeviceVO device, BigDecimal amount, String reason, boolean requiredIot) {
ServiceUtil.assertion(device == null || device.getDeviceId() == null, "设备不存在");
ServiceUtil.assertion(amount == null, "增加的电量不能为空");
ServiceUtil.assertion( amount.compareTo(BigDecimal.ZERO) < 0, "增加的电量不允许小于0");
ServiceUtil.assertion(StringUtils.isAllBlank(device.getMac(), device.getMac2()), "设备MAC号为空");
ServiceUtil.assertion(DeviceStatus.FIXING.getStatus().equals(device.getStatus()), "设备正在维修中,无法使用");
DeviceIotResultVO vo = new DeviceIotResultVO();
Integer result = transactionTemplate.execute(status -> {
// 更新设备电量
int update = deviceMapper.addEle(device.getDeviceId(), amount);
int update = this.addEleDb(device.getDeviceId(), amount);
ServiceUtil.assertion(update != 1, "更新电量失败");
// 操作物联网设备
try {
CommandResponse res;
// 若设备剩余电量大于0则补偿电量充值
if (device.getSurplusEle().compareTo(BigDecimal.ZERO) > 0) {
res = iotService.setEle(device, amount.add(device.getSurplusEle()), reason);
} else {
res = iotService.setEle(device, amount, reason);
}
CommandResponse res = this.syncEle(device.getDeviceId(), reason);
ServiceUtil.assertion(res == null, "电量充值失败:未知错误");
ServiceUtil.assertion(!res.isSuccess(), "为设备充值电量失败:%s", res.getMsg());
} catch (Exception e) {
vo.setIot(false);
vo.setMsg(e.getMessage());
if (requiredIot) {
throw e;
}
@ -544,9 +532,8 @@ public class DeviceServiceImpl implements DeviceService
return update;
});
vo.setDb(result);
return vo;
return result != null && result == 1;
}
@Override
@ -721,13 +708,13 @@ public class DeviceServiceImpl implements DeviceService
@Override
public DeviceIotResultVO addTime(Long deviceId, long seconds, String reason, boolean requiredIot) {
public boolean addTime(Long deviceId, long seconds, String reason, boolean requiredIot) {
DeviceVO device = deviceMapper.selectSmDeviceByDeviceId(deviceId);
return addTime(device, seconds, reason, requiredIot);
}
@Override
public DeviceIotResultVO addTime(DeviceVO device, long seconds, String reason, boolean requiredIot) {
public boolean addTime(DeviceVO device, long seconds, String reason, boolean requiredIot) {
ServiceUtil.assertion( seconds < 0, "增加的时长不允许小于0");
ServiceUtil.assertion(device == null || device.getDeviceId() == null, "设备不存在");
ServiceUtil.assertion(StringUtils.isAllBlank(device.getMac(), device.getMac2()), "设备MAC号为空");
@ -735,26 +722,18 @@ public class DeviceServiceImpl implements DeviceService
Long deviceId = device.getDeviceId();
LocalDateTime now = LocalDateTime.now();
DeviceIotResultVO vo = new DeviceIotResultVO();
Integer result = transactionTemplate.execute(status -> {
// 更新数据库时长
int updateCount = deviceMapper.addTime(deviceId, seconds);
int updateCount = this.addTimeDb(deviceId, seconds);
ServiceUtil.assertion(updateCount != 1, "增加时长失败,请刷新后重试");
// 尝试操作物联网设备
// 同步物联网设备时长
try {
DeviceVO newDevice = selectById(deviceId);
long betweenSeconds = Duration.between(now, newDevice.getExpireTime()).getSeconds();
if (betweenSeconds > 0) {
CommandResponse rechargeResult = iotService.setTime(device, betweenSeconds, reason);
ServiceUtil.assertion(!rechargeResult.isSuccess(), "设备充值失败,请检查设备是否在线");
}
vo.setIot(true);
vo.setMsg("成功");
CommandResponse res = this.syncTime(deviceId, now, reason);
ServiceUtil.assertion(res == null, "设备充值失败:未知错误");
ServiceUtil.assertion(!res.isSuccess(), "设备充值失败:%s", res.getMsg());
} catch (Exception e) {
vo.setIot(false);
vo.setMsg(e.getMessage());
if (requiredIot) {
throw e;
}
@ -762,7 +741,6 @@ public class DeviceServiceImpl implements DeviceService
return updateCount;
});
vo.setDb(result);
// 成功后拉取设备信息
boolean success = result != null && result == 1;
@ -770,7 +748,7 @@ public class DeviceServiceImpl implements DeviceService
this.pullDeviceInfoAsync(Collections.singletonList(deviceId), 3, TimeUnit.SECONDS);
}
return vo;
return success;
}
@Override
@ -1034,7 +1012,10 @@ public class DeviceServiceImpl implements DeviceService
device.setOnlineStatus(DeviceOnlineStatus.OFFLINE.getStatus());
}
this.updateIotInfo(device);
// 异步更新
scheduledExecutorService.schedule(() -> {
this.updateIotInfo(device);
}, 0, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("更新设备信息失败deviceId:{}, {}", device.getDeviceId(), e.getMessage());
}
@ -1277,6 +1258,62 @@ public class DeviceServiceImpl implements DeviceService
return res != null && res.isSuccess() ? 1 : 0;
}
/**
* 增加数据库设备时长
*
* @param deviceId 设备ID
* @param seconds
* @return
*/
@Override
public int addTimeDb(Long deviceId, long seconds) {
if (deviceId == null || seconds <= 0) {
return 0;
}
return deviceMapper.addTime(deviceId, seconds);
}
@Override
public int addEleDb(Long deviceId, BigDecimal amount) {
if (deviceId == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
return 0;
}
return deviceMapper.addEle(deviceId, amount);
}
@Override
public CommandResponse syncTime(Long deviceId, LocalDateTime now, String reason) {
if (deviceId == null) {
return null;
}
if (now == null) {
now = LocalDateTime.now();
}
DeviceVO device = selectById(deviceId);
long betweenSeconds = Duration.between(now, device.getExpireTime()).getSeconds();
if (betweenSeconds > 0) {
return iotService.setTime(device, betweenSeconds, reason);
}
return null;
}
@Override
public CommandResponse syncEle(Long deviceId, String reason) {
if (deviceId == null) {
return null;
}
DeviceVO device = selectById(deviceId);
// 若设备剩余电量大于0则补偿电量充值
// if (device.getSurplusEle().compareTo(BigDecimal.ZERO) > 0) {
// res = iotService.setEle(device, amount.add(device.getSurplusEle()), reason);
// } else {
// res = iotService.setEle(device, amount, reason);
// }
return iotService.setEle(device, device.getSurplusEleDb(), reason);
}
/**
* 设备是否已经被绑定
*

View File

@ -1,5 +1,6 @@
package com.ruoyi.ss.transactionBill.domain.bo;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.payBill.domain.PayBillVO;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
@ -16,6 +17,9 @@ public class PaySuccessBO {
// 支付订单
private PayBillVO payBill;
// 设备
private DeviceVO device;
// 充值订单
private TransactionBillVO order;

View File

@ -193,13 +193,6 @@ public interface TransactionBillService
*/
int updateByQuery(TransactionBill data, TransactionBillQuery query);
/**
* 尝试充值设备
* @param billId 订单ID
* @param tryCount 尝试次数
*/
void tryRechargeDevice(Long billId, int tryCount);
/**
* 尝试设置语音
*/

View File

@ -1,10 +1,15 @@
package com.ruoyi.ss.transactionBill.service.impl;
import com.ruoyi.common.constant.IotConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.bonus.domain.enums.BonusArrivalType;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.device.domain.vo.DeviceIotResultVO;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.payBill.domain.PayBillVO;
import com.ruoyi.ss.payBill.domain.bo.RefundSuccessBO;
import com.ruoyi.ss.payBill.domain.dto.PayBillRefundDTO;
@ -61,6 +66,9 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
@Autowired
private TransactionBillConverter transactionBillConverter;
@Autowired
private DeviceService deviceService;
@Override
public int onPaySuccess(PayBillVO payBill) {
TransactionBillVO bill = transactionBillService.selectSmTransactionBillByBillId(payBill.getBstId());
@ -71,6 +79,7 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
PaySuccessBO bo = new PaySuccessBO();
bo.setOrder(bill);
bo.setPayBill(payBill);
bo.setDevice(deviceService.selectById(bill.getDeviceId()));
// 拼接分成列表
transactionAssembler.assembleBonusList(bill);
@ -90,6 +99,10 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
ServiceUtil.assertion(bill == null || !TransactionBillType.RECHARGE.getType().equals(bill.getType()), "充值订单不存在");
ServiceUtil.assertion(!TransactionBillStatus.UNPAID.getStatus().equals(bill.getStatus()), "当前订单状态非未支付");
// 设备信息
DeviceVO device = bo.getDevice();
deviceService.pullDeviceInfo(device, IotConstants.ONLINE_TYPE_GET);
List<BonusVO> bonusList = bill.getBonusList();
Integer result = transactionTemplate.execute(status -> {
@ -143,6 +156,15 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
int received = transactionBillService.receiveMchShowMobileAmount(bill);
ServiceUtil.assertion(received != 1, "商户获取用户手机号扣款失败");
// 修改设备数据库余额
if (SuitFeeType.TIME.getType().equals(bill.getSuitFeeType())) {
int addDb = deviceService.addTimeDb(bill.getDeviceId(), bill.getRechargeSeconds());
ServiceUtil.assertion(addDb != 1, "设备数据库余额增加失败");
} else if (SuitFeeType.COUNT.getType().equals(bill.getSuitFeeType())) {
int addDb = deviceService.addEleDb(bill.getDeviceId(), bill.getRechargeEle());
ServiceUtil.assertion(addDb != 1, "设备数据库余额增加失败");
}
return updateCount;
});

View File

@ -869,24 +869,17 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
// 充值设备
Boolean iotResult = transactionTemplate.execute(status -> {
// 充值设备
DeviceIotResultVO res = null;
// 同步设备余额
CommandResponse res = null;
if (SuitFeeType.TIME.getType().equals(bill.getSuitFeeType())) {
// 设备设置时长
long seconds = bill.getRechargeSeconds();
res = deviceService.addTime(device, seconds, "充值订单:" + bill.getBillNo(), false);
res = deviceService.syncTime(bill.getDeviceId(), LocalDateTime.now(), "充值订单:" + bill.getBillNo());
} else if (SuitFeeType.COUNT.getType().equals(bill.getSuitFeeType())) {
// 设备增加电量
BigDecimal ele = bill.getRechargeEle();
res = deviceService.addEle(device, ele, "充值订单:" + bill.getBillNo(), false);
} else {
throw new ServiceException("不支持的套餐类型");
res = deviceService.syncEle(bill.getDeviceId(), "充值订单:" + bill.getBillNo());
}
// 充值结果
TransactionBill data = new TransactionBill();
if (res != null && res.getDb() != null && res.getDb() == 1 && res.getIot() != null && res.getIot()) {
if (res != null && res.isSuccess()) {
data.setDeviceRechargeStatus(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus());
data.setOpenMsg("成功");
} else {
@ -989,24 +982,6 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return transactionBillMapper.updateSmTransactionBill(data);
}
/**
* 异步尝试充值设备
* @param billId
* @param tryCount
*/
@Override
public void tryRechargeDevice(Long billId, int tryCount) {
if (tryCount <= 0) {
return;
}
try {
boolean result = rechargeDevice(billId);
ServiceUtil.assertion(!result, String.format("尝试充值设备失败:billId=%s:剩余次数:%s,", billId, tryCount - 1));
} catch (Exception e) {
this.tryRechargeDevice(billId, tryCount - 1);
}
}
@Override
public DoPayVO payDeposit(RechargePayDepositBO bo) {
// 校验
@ -1431,17 +1406,18 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return total;
}
public static void main(String[] args) {
List<BigDecimal> suitGearAmount = Arrays.asList(new BigDecimal(0.22), new BigDecimal("0.39"), new BigDecimal("0.59"), new BigDecimal("0.89"));
List<Integer> suitGearTime = Arrays.stream("1,1,1,1,1,1,1,2,2,2,1,0,0,0,1,2,3,3,3,2,2,2,2,1".split(",")).map(Integer::parseInt).collect(Collectors.toList());
LocalDateTime startTime = DateUtils.toLocalDateTime("2024-12-19 12:45:31");
LocalDateTime endTime = DateUtils.toLocalDateTime("2024-12-20 14:58:35");
BigDecimal usedEle = new BigDecimal(13.8); // 总用电量 13.8
TransactionBillServiceImpl service = new TransactionBillServiceImpl();
BigDecimal total = service.calcTimingCountAmount(suitGearAmount, suitGearTime, startTime, endTime, usedEle);
System.out.println(total);
}
// 测试总用电量
// public static void main(String[] args) {
// List<BigDecimal> suitGearAmount = Arrays.asList(new BigDecimal(0.22), new BigDecimal("0.39"), new BigDecimal("0.59"), new BigDecimal("0.89"));
// List<Integer> suitGearTime = Arrays.stream("1,1,1,1,1,1,1,2,2,2,1,0,0,0,1,2,3,3,3,2,2,2,2,1".split(",")).map(Integer::parseInt).collect(Collectors.toList());
// LocalDateTime startTime = DateUtils.toLocalDateTime("2024-12-19 12:45:31");
// LocalDateTime endTime = DateUtils.toLocalDateTime("2024-12-20 14:58:35");
// BigDecimal usedEle = new BigDecimal(13.8); // 总用电量 13.8
//
// TransactionBillServiceImpl service = new TransactionBillServiceImpl();
// BigDecimal total = service.calcTimingCountAmount(suitGearAmount, suitGearTime, startTime, endTime, usedEle);
// System.out.println(total);
// }
// 计算分时段计时金额
private BigDecimal calcTimingTimeAmount(TransactionBillVO order, LocalDateTime endTime) {

View File

@ -197,8 +197,7 @@ public class AppDeviceController extends BaseController {
// 电量
if ( "0".equals(timeUnit)) {
DeviceIotResultVO vo = smDeviceService.addEle(deviceId, amount, "商户手动充值", true);
return toAjax(vo.getIot());
return toAjax(smDeviceService.addEle(deviceId, amount, "商户手动充值", true));
}
// 时长
else {
@ -207,8 +206,7 @@ public class AppDeviceController extends BaseController {
return error("非法的时长单位");
}
long seconds = amount.multiply(new BigDecimal(unit.getConversion())).longValue();
DeviceIotResultVO vo = smDeviceService.addTime(deviceId, seconds, "商户手动充值", true);
return toAjax(vo.getIot());
return toAjax(smDeviceService.addTime(deviceId, seconds, "商户手动充值", true));
}
}

View File

@ -165,8 +165,7 @@ public class SmDeviceController extends BaseController
if (unit == null) {
return error("非法的时长单位");
}
DeviceIotResultVO vo = deviceService.addTime(deviceId, amount * unit.getConversion(), "管理员手动充值时长", true);
return toAjax(vo.getIot());
return toAjax(deviceService.addTime(deviceId, amount * unit.getConversion(), "管理员手动充值时长", true));
}
@PreAuthorize("@ss.hasPermi('system:device:addEle')")
@ -174,8 +173,7 @@ public class SmDeviceController extends BaseController
@PutMapping("/addEle/{deviceId}")
public AjaxResult addEle(@ApiParam("设备id") @PathVariable Long deviceId,
@ApiParam("电量(度)") @RequestParam BigDecimal amount) {
DeviceIotResultVO vo = deviceService.addEle(deviceId, amount, "管理员手动充值电量", true);
return toAjax(vo.getIot());
return toAjax(deviceService.addEle(deviceId, amount, "管理员手动充值电量", true));
}
@ApiOperation("设备时长归零")