diff --git a/smart-switch-service/src/main/java/com/ruoyi/iot/receive/ReceiveController.java b/smart-switch-service/src/main/java/com/ruoyi/iot/receive/ReceiveController.java index 30f5d97b..13f7059f 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/iot/receive/ReceiveController.java +++ b/smart-switch-service/src/main/java/com/ruoyi/iot/receive/ReceiveController.java @@ -18,6 +18,8 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * 接收硬件参数 @@ -34,10 +36,10 @@ public class ReceiveController { private String token; @Autowired - private IotService iotService; + private IotReceiveService iotReceiveService; @Autowired - private IotReceiveService iotReceiveService; + private ScheduledExecutorService scheduledExecutorService; /** * 功能描述:第三方平台数据接收。

@@ -52,11 +54,11 @@ public class ReceiveController { @PostMapping(value = "/receive") @Anonymous public ResponseEntity receive(HttpServletRequest request){ - String body = HttpUtils.getBody(request); - ObjBody obj = IotUtil.resolveBody(body, false); - if (obj != null){ -// if (IotUtil.checkSignature(obj, token)){ -// log.info("receive成功参数:" + body); + // 异步处理,直接返回成功 + scheduledExecutorService.schedule(() -> { + String body = HttpUtils.getBody(request); + ObjBody obj = IotUtil.resolveBody(body, false); + if (obj != null){ Object msg = obj.getMsg(); // 接收到msg if (msg instanceof String) { @@ -64,12 +66,10 @@ public class ReceiveController { } else { iotReceiveService.handleReceive(JSON.parseObject(JSON.toJSONString(msg), ReceiveMsg.class)); } -// }else { -// log.error("receive签名错误:" + body); -// } - }else { - log.error("receive方法参数为空: body empty error"); - } + }else { + log.error("receive方法参数为空: body empty error"); + } + }, 0, TimeUnit.SECONDS); return new ResponseEntity<>(HttpStatus.OK); } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/domain/Device.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/domain/Device.java index 8b540a51..eb8166f1 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/domain/Device.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/domain/Device.java @@ -259,4 +259,17 @@ public class Device extends BaseEntity @ApiModelProperty("电压系数") private BigDecimal vxs; + + @Excel(name = "用户手动操作类型", readConverterExp = "1=开启,2=关闭") + @ApiModelProperty("用户手动操作类型") + private String userOperaType; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "用户手动操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("用户手动操作时间") + private LocalDateTime userOperaTime; + + @Excel(name = "用户手动操作时的总用电量") + @ApiModelProperty("用户手动操作时的总用电量") + private BigDecimal userOperaEle; } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/domain/enums/DeviceUserOperaType.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/domain/enums/DeviceUserOperaType.java new file mode 100644 index 00000000..28af01b7 --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/domain/enums/DeviceUserOperaType.java @@ -0,0 +1,21 @@ +package com.ruoyi.ss.device.domain.enums; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; + +/** + * @author wjh + * 2024/12/26 + */ +@Getter +@AllArgsConstructor +public enum DeviceUserOperaType { + + OPEN("1", "开启"), + CLOSE("2", "关闭"); + + private final String type; + private final String msg; + +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/DeviceMapper.xml b/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/DeviceMapper.xml index ab7c94e2..69e887f1 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/DeviceMapper.xml +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/DeviceMapper.xml @@ -69,6 +69,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" sd.expire_ele, sd.last_init_reading, sd.vxs, + sd.user_opera_type, + sd.user_opera_time, + sd.user_opera_ele, sm.model_name as model, sm.picture as picture, sm.tags as model_tags, @@ -132,6 +135,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and sd.version like concat('%', #{query.version}, '%') and find_in_set(#{query.modelTag}, sm.tags) and sd.device_id != #{query.excludeDeviceId} + and user_opera_type = #{query.userOperaType} and sd.store_id not @@ -396,6 +400,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" expire_ele, last_init_reading, vxs, + user_opera_type, + user_opera_time, + user_opera_ele, #{storeId}, @@ -451,6 +458,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{expireEle}, #{lastInitReading}, #{vxs}, + #{userOperaType}, + #{userOperaTime}, + #{userOperaEle}, @@ -537,6 +547,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" expire_ele = #{expireEle}, last_init_reading = #{lastInitReading}, vxs = #{vxs}, + user_opera_type = #{userOperaType}, + user_opera_time = #{userOperaTime}, + user_opera_ele = #{userOperaEle}, where device_id = #{deviceId} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java index 123b4b98..e3dd5288 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java @@ -21,10 +21,7 @@ import com.ruoyi.ss.device.domain.DeviceQuery; 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.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.enums.*; import com.ruoyi.ss.device.domain.vo.DeviceMacSnVO; import com.ruoyi.ss.device.domain.vo.DeviceVO; import com.ruoyi.ss.device.mapper.DeviceMapper; @@ -369,6 +366,7 @@ public class DeviceServiceImpl implements DeviceService @Override public int switchDevice(Long deviceId, boolean open, String reason) { DeviceVO device = selectById(deviceId); + this.pullDeviceInfo(device, IotConstants.ONLINE_TYPE_GET); return this.switchDevice(device, open ? DevicePowerStatus.ON : DevicePowerStatus.OFF, reason); } @@ -813,10 +811,10 @@ public class DeviceServiceImpl implements DeviceService // 校验 this.validatePreLogicDelete(deviceIds); - // 拉取最新数据 - this.pullDeviceInfo(deviceIds, IotConstants.ONLINE_TYPE_GET); // 查询设备列表 List deviceList = this.selectByIds(deviceIds); + // 拉取最新数据 + this.pullDeviceInfoList(deviceList, IotConstants.ONLINE_TYPE_GET); Integer result = transactionTemplate.execute(status -> { // 关闭设备订单 @@ -867,7 +865,7 @@ public class DeviceServiceImpl implements DeviceService /** * 切换设备通电状态(通/断电) * - * @param device 设备id + * @param device 设备id * @param powerStatus 通电状态 * @param reason */ @@ -876,18 +874,27 @@ public class DeviceServiceImpl implements DeviceService ServiceUtil.assertion(device == null || device.getDeleted(), "设备不存在"); Integer result = transactionTemplate.execute(status -> { - // 修改数据库通断电状态 - Device changePowerForm = new Device(); - changePowerForm.setDeviceId(device.getDeviceId()); - changePowerForm.setPowerStatus(powerStatus.getStatus()); - int update = deviceMapper.updateSmDevice(changePowerForm); + // 修改数据库 + Device data = new Device(); + data.setDeviceId(device.getDeviceId()); + data.setPowerStatus(powerStatus.getStatus()); + data.setUserOperaTime(LocalDateTime.now()); + data.setUserOperaEle(device.getTotalElectriQuantity()); + if (DevicePowerStatus.ON.equals(powerStatus)) { + data.setUserOperaType(DeviceUserOperaType.OPEN.getType()); + } else { + data.setUserOperaType(DeviceUserOperaType.CLOSE.getType()); + } + int update = deviceMapper.updateSmDevice(data); // 操作设备 if (update == 1) { if (DevicePowerStatus.ON.equals(powerStatus)) { - iotService.open(device, reason); + boolean open = iotService.open(device, reason); + ServiceUtil.assertion(!open, "开启设备失败"); } else if (DevicePowerStatus.OFF.equals(powerStatus)) { - iotService.close(device, reason); + boolean close = iotService.close(device, reason); + ServiceUtil.assertion(!close, "关闭设备失败"); } else { throw new ServiceException("不支持的操作"); } @@ -1308,7 +1315,9 @@ public class DeviceServiceImpl implements DeviceService return iotService.setEle(device, device.getSurplusEleDb(), reason); } - // 监控设备信息,并对设备进行校准 + /** + * 监控设备信息,并对设备进行校准 + */ @Override public void monitor(List deviceIds) { DeviceQuery query = new DeviceQuery(); @@ -1321,23 +1330,30 @@ public class DeviceServiceImpl implements DeviceService for (DeviceVO device : deviceList) { try { - scheduledExecutorService.schedule(() -> { // 若物联网设备的时长或者电量小于当前设备数据库的值,则执行一次同步(开启) // 一般情况下,物联网设备的值会大于或等于当前数据库的值 long deviceSeconds = device.getRemainTime() == null ? 0 : device.getRemainTime().longValue(); if (device.getSurplusSecondsDb() > deviceSeconds) { - this.syncTime(device.getDeviceId(), LocalDateTime.now(), "设备监控-同步时长"); + this.syncTime(device.getDeviceId(), LocalDateTime.now(), "设备监控-同步ch时长"); } if (device.getSurplusEleDb().compareTo(device.getSurplusEle()) > 0) { this.syncEle(device.getDeviceId(), "设备监控-同步电量"); } - // TODO 若当前设备数据库的时长或者电量<=0,且在这之后用户没有发open命令,则执行一次同步(关闭) - if (device.getSurplusSecondsDb() <= 0) { - // TODO + + // 若当前设备数据库的时长或者电量<=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, "设备监控-发现异常未关闭设备"); } - if (device.getSurplusEle().compareTo(device.getSurplusEleDb()) <= 0) { - // TODO + + boolean hasOpenAfterExpireEle = hasOpen && lastOperaEle != null && lastOperaEle.compareTo(device.getExpireEle()) > 0; // 是否在结束电量后开启 + if (device.getSurplusEle().compareTo(device.getSurplusEleDb()) <= 0 && !hasOpenAfterExpireEle) { + this.switchDevice(device, DevicePowerStatus.OFF, "设备监控-发现异常未关闭设备"); } },0, TimeUnit.SECONDS); @@ -1345,9 +1361,6 @@ public class DeviceServiceImpl implements DeviceService log.error("监控设备{}出错:{}", device.getDeviceNo(), e.getMessage()); } } - - - } /** diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/RechargeDepositAfterPay.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/RechargeDepositAfterPay.java index 66f94b41..1130523e 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/RechargeDepositAfterPay.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/RechargeDepositAfterPay.java @@ -4,6 +4,7 @@ import com.ruoyi.common.constant.IotConstants; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.iot.service.IotService; +import com.ruoyi.ss.device.domain.enums.DevicePowerStatus; import com.ruoyi.ss.device.domain.vo.DeviceVO; import com.ruoyi.ss.device.service.DeviceService; import com.ruoyi.ss.payBill.domain.PayBillVO; @@ -47,10 +48,9 @@ public class RechargeDepositAfterPay implements AfterPay { ServiceUtil.assertion(bill == null, "订单不存在"); ServiceUtil.assertion(!TransactionBillStatus.UNPAID_DEPOSIT.getStatus().equals(bill.getStatus()), "订单状态非待支付押金"); - deviceService.pullDeviceInfo(bill.getDeviceId(), IotConstants.ONLINE_TYPE_GET); - DeviceVO device = deviceService.selectById(bill.getDeviceId()); ServiceUtil.assertion(device == null, "设备不存在"); + deviceService.pullDeviceInfo(device, IotConstants.ONLINE_TYPE_GET); Integer result = transactionTemplate.execute(status -> { // 修改订单信息 @@ -60,8 +60,6 @@ public class RechargeDepositAfterPay implements AfterPay { data.setStatus(TransactionBillStatus.SUCCESS_DEPOSIT.getStatus()); data.setDepositPayId(payBill.getPayId()); data.setPayTime(DateUtils.toDate(payBill.getPayTime())); - data.setDeviceRechargeStatus(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus()); - data.setOpenMsg("成功"); TransactionBillQuery query = new TransactionBillQuery(); query.setBillId(bill.getBillId()); query.setStatus(TransactionBillStatus.UNPAID_DEPOSIT.getStatus()); @@ -72,28 +70,43 @@ public class RechargeDepositAfterPay implements AfterPay { int received = transactionBillService.receiveMchShowMobileAmount(bill); ServiceUtil.assertion(received != 1, "商户获取用户手机号扣款失败"); - // 开启设备 - this.openDevice(bill); - return update; }); + // 开启设备 + this.openDevice(bill, device); + return result == null ? 0 : result; } /** * 订单开启设备 */ - private int openDevice(TransactionBillVO bill) { + private int openDevice(TransactionBillVO bill, DeviceVO device) { try { - iotService.open(bill, "分时段订单" + bill.getBillNo() + "开启"); - return 1; + Integer result = transactionTemplate.execute(status -> { + // 修改订单信息 + TransactionBill data = new TransactionBill(); + data.setBillId(bill.getBillId()); + data.setDeviceRechargeStatus(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus()); + data.setOpenMsg("成功"); + int update = transactionBillService.updateSmTransactionBill(data); + ServiceUtil.assertion(update != 1, "修改订单信息失败,状态已经发生改变:%s", bill.getBillNo()); + + // 操作设备 + int switchDevice = deviceService.switchDevice(device, DevicePowerStatus.ON, "分时段订单" + bill.getBillNo() + "开启"); + ServiceUtil.assertion(switchDevice != 1, "操作设备%s失败", device.getDeviceNo()); + + return update; + }); + + return result == null ? 0 : result; } catch (Exception e) { log.error(e.getMessage()); TransactionBill data = new TransactionBill(); + data.setBillId(bill.getBillId()); data.setDeviceRechargeStatus(TransactionBillDeviceRechargeStatus.FAIL.getStatus()); data.setOpenMsg(e.getMessage()); - data.setBillId(bill.getBillId()); return transactionBillService.updateSmTransactionBill(data); } } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java index 51f67b58..9d125b58 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java @@ -24,7 +24,7 @@ import com.ruoyi.ss.bonus.service.BonusService; import com.ruoyi.ss.channelWithdraw.domain.ChannelWithdrawVO; import com.ruoyi.ss.channelWithdraw.service.ChannelWithdrawService; import com.ruoyi.dashboard.domain.vo.BillCountVo; -import com.ruoyi.ss.device.domain.vo.DeviceIotResultVO; +import com.ruoyi.ss.device.domain.enums.DevicePowerStatus; import com.ruoyi.ss.device.domain.vo.DeviceVO; import com.ruoyi.ss.device.service.DeviceService; import com.ruoyi.ss.payBill.domain.PayBillQuery; @@ -1049,7 +1049,8 @@ public class TransactionBillServiceImpl implements TransactionBillService, After } else if(SuitFeeType.TIMING_TIME.getType().equals(order.getSuitFeeType())){ deviceService.resetTime(device, false, reason); } - iotService.close(device, reason); + int switchDevice = deviceService.switchDevice(device, DevicePowerStatus.OFF, reason); + ServiceUtil.assertion(switchDevice != 1, "操作设备失败"); } return update; @@ -1919,28 +1920,23 @@ public class TransactionBillServiceImpl implements TransactionBillService, After DeviceVO device = deviceService.selectById(bill.getDeviceId()); ServiceUtil.assertion(device == null, "设备不存在"); - ServiceUtil.assertion(StringUtils.isBlank(device.getMac()), "设备MAC为空,请联系管理员处理"); + ServiceUtil.assertion(StringUtils.isAllBlank(device.getMac(), device.getMac2()), "设备MAC为空,请联系管理员处理"); + deviceService.pullDeviceInfo(device, IotConstants.ONLINE_TYPE_GET); + // 开启 if (open) { + // 分时段订单,直接open if (SuitFeeType.timingList().contains(bill.getSuitFeeType())) { - return iotService.open(device, "订单" + bill.getBillNo() + "临时开启") ? 1 : 0; - } else { - // 计算设备剩余时长 - LocalDateTime expireTime = device.getExpireTime(); - if (expireTime == null) { - return 0; - } - Duration between = Duration.between(LocalDateTime.now(), expireTime); - if (between.getSeconds() > 0) { - CommandResponse res = iotService.setTime(device, between.getSeconds(), "订单" + bill.getBillNo() + "临时开启"); - return res.isSuccess() ? 1 : 0; - } + return deviceService.switchDevice(device, DevicePowerStatus.ON, "分时段订单" + bill.getBillNo() + "临时开启"); + } + // 其余订单,同步时长 + else { + CommandResponse res = deviceService.syncTime(device.getDeviceId(), LocalDateTime.now(), "时长订单" + bill.getBillNo() + "临时开启"); + return res != null && res.isSuccess() ? 1 : 0; } } else { - return iotService.close(device, "订单" + bill.getBillNo() + "临时关闭") ? 1 : 0; + return deviceService.switchDevice(device, DevicePowerStatus.OFF, "订单" + bill.getBillNo() + "临时关闭"); } - - return 0; } @Override diff --git a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java index d7b3554c..705d49fb 100644 --- a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java +++ b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java @@ -20,7 +20,6 @@ import com.ruoyi.ss.device.domain.DeviceQuery; 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.DeviceVO; import com.ruoyi.ss.device.service.DeviceAssembler; import com.ruoyi.ss.device.service.DeviceConverter; @@ -130,15 +129,19 @@ public class AppDeviceController extends BaseController { @ApiOperation("设备通断电") @PutMapping("/{deviceId}/changePower") public AjaxResult close(@PathVariable @ApiParam("设备id") Long deviceId, String status) { + DeviceVO device = smDeviceService.selectById(deviceId); + ServiceUtil.assertion(device == null, "设备不存在"); + // 判断是否有权限更改 if (!deviceValidator.canOpera(deviceId, getUserId()) ) { return error("您无权操作此设备"); } - DeviceVO device = smDeviceService.selectById(deviceId); - ServiceUtil.assertion(device == null, "设备不存在"); deviceAssembler.assembleAllowSwitch(device, getUserId()); ServiceUtil.assertion(!device.getAllowSwitch(), "您无权操作此设备"); + // 获取最新数据 + smDeviceService.pullDeviceInfo(device, IotConstants.ONLINE_TYPE_GET); + DevicePowerStatus powerStatus = DevicePowerStatus.parse(status); return toAjax(smDeviceService.switchDevice(device, powerStatus, "商户开关设备")); }