소스 검색

Merge branch 'master' into prod

李进 1 년 전
부모
커밋
a6dacc1d56
50개의 변경된 파일1895개의 추가작업 그리고 146개의 파일을 삭제
  1. 10 0
      device-api-cloud/src/main/java/com/xy/feign/DeviceDataFeign.java
  2. 41 15
      device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceController.java
  3. 4 0
      device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceHomePageController.java
  4. 7 2
      device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceRecordsController.java
  5. 0 2
      device-api-service-merc-mini/src/main/java/com/xy/dto/MiniDeviceRecordsDto.java
  6. 10 3
      device-api-service/pom.xml
  7. 39 0
      device-api-service/src/main/java/com/xy/alipay/AliPay.java
  8. 141 0
      device-api-service/src/main/java/com/xy/alipay/AliPayAspet.java
  9. 24 0
      device-api-service/src/main/java/com/xy/consumer/connected/ConnectedMqttConfiguration.java
  10. 26 0
      device-api-service/src/main/java/com/xy/consumer/connected/ConnectedProducer.java
  11. 24 0
      device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedMqttConfiguration.java
  12. 26 0
      device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedProducer.java
  13. 45 0
      device-api-service/src/main/java/com/xy/entity/DeviceCharging.java
  14. 44 0
      device-api-service/src/main/java/com/xy/entity/DeviceChargingHistory.java
  15. 3 13
      device-api-service/src/main/java/com/xy/entity/DeviceErrorsRecord.java
  16. 171 0
      device-api-service/src/main/java/com/xy/job/DeviceChargingJob.java
  17. 16 0
      device-api-service/src/main/java/com/xy/mapper/DeviceChargingHistoryMapper.java
  18. 36 0
      device-api-service/src/main/java/com/xy/mapper/DeviceChargingMapper.java
  19. 10 1
      device-api-service/src/main/java/com/xy/mapper/DeviceDataMapper.java
  20. 1 0
      device-api-service/src/main/java/com/xy/mapper/DeviceInfoMapper.java
  21. 18 0
      device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingHistoryMapper.xml
  22. 18 0
      device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingMapper.xml
  23. 57 0
      device-api-service/src/main/java/com/xy/service/DeviceChargingHistoryServiceImpl.java
  24. 89 0
      device-api-service/src/main/java/com/xy/service/DeviceChargingServiceImpl.java
  25. 2 2
      device-api-service/src/main/java/com/xy/service/DeviceCreateIdsServiceImpl.java
  26. 43 0
      device-api-service/src/main/java/com/xy/service/DeviceDataServiceImpl.java
  27. 24 10
      device-api-service/src/main/java/com/xy/service/DeviceErrorsRecordServiceImpl.java
  28. 54 35
      device-api-service/src/main/java/com/xy/service/DeviceInfoServiceImpl.java
  29. 99 0
      device-api-service/src/main/java/com/xy/service/DeviceRegisterServiceImpl.java
  30. 2 1
      device-api-service/src/main/java/com/xy/service/MqttServiceImpl.java
  31. 5 0
      device-api-service/src/main/java/com/xy/utils/enums/DictEnum.java
  32. 10 0
      device-api-service/src/main/java/com/xy/utils/enums/DictSonEnum.java
  33. 17 0
      device-api-service/src/main/java/com/xy/utils/enums/SysCodeConfigureEnum.java
  34. 59 0
      device-api-service/src/main/resources/mapper/DeviceChargingMapper.xml
  35. 12 0
      device-api-service/src/main/resources/mapper/DeviceDataMapper.xml
  36. 1 1
      device-api-service/src/main/resources/mapper/DeviceInfoMapper.xml
  37. 95 0
      device-api/src/main/java/com/xy/dto/DeviceChargingDto.java
  38. 64 0
      device-api/src/main/java/com/xy/dto/DeviceChargingHistoryDto.java
  39. 94 10
      device-api/src/main/java/com/xy/dto/DeviceDataDto.java
  40. 5 11
      device-api/src/main/java/com/xy/dto/DeviceErrorsRecordDto.java
  41. 43 2
      device-api/src/main/java/com/xy/dto/DeviceInfoDto.java
  42. 79 0
      device-api/src/main/java/com/xy/dto/MercMiniDeviceDto.java
  43. 201 0
      device-api/src/main/java/com/xy/dto/MercMiniSalseCountDto.java
  44. 16 0
      device-api/src/main/java/com/xy/service/DeviceChargingHistoryService.java
  45. 16 0
      device-api/src/main/java/com/xy/service/DeviceChargingService.java
  46. 27 0
      device-api/src/main/java/com/xy/service/DeviceDataService.java
  47. 14 8
      device-api/src/main/java/com/xy/utils/enums/DeviceErrorRecordTypesEnum.java
  48. 0 28
      device-api/src/main/java/com/xy/utils/enums/DeviceErrorTypesEnum.java
  49. 48 0
      device-api/src/main/java/com/xy/utils/enums/DeviceLockState.java
  50. 5 2
      device-start/pom.xml

+ 10 - 0
device-api-cloud/src/main/java/com/xy/feign/DeviceDataFeign.java

@@ -0,0 +1,10 @@
+package com.xy.feign;
+
+import com.xy.FeignInterceptor;
+import com.xy.consts.ServiceConsts;
+import com.xy.service.DeviceDataService;
+import org.springframework.cloud.openfeign.FeignClient;
+
+@FeignClient(value = ServiceConsts.SERVICE_NAME, configuration = FeignInterceptor.class)
+public interface DeviceDataFeign extends DeviceDataService {
+}

+ 41 - 15
device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceController.java

@@ -3,6 +3,7 @@ package com.xy.controller;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.xy.alipay.AliPay;
 import com.xy.annotate.RestMappingController;
 import com.xy.dto.DeviceBluetoothAuthDto;
 import com.xy.dto.DeviceInfoDto;
@@ -12,24 +13,21 @@ import com.xy.dto.be.MercDto;
 import com.xy.dto.common.MercLineDto;
 import com.xy.dto.common.MercPlaceDto;
 import com.xy.dto.mini.MiniMercRegionDto;
-import com.xy.entity.DeviceBluetoothAuth;
-import com.xy.entity.DeviceInfo;
-import com.xy.entity.DeviceSysinfo;
+import com.xy.entity.*;
 import com.xy.enums.MercStatus;
 import com.xy.service.DeviceBluetoothAuthServiceImpl;
+import com.xy.service.DeviceChargingServiceImpl;
 import com.xy.service.DeviceInfoServiceImpl;
 import com.xy.service.DeviceSysinfoServiceImpl;
 import com.xy.service.be.MercFeignService;
 import com.xy.service.common.MercLineService;
 import com.xy.service.common.MercPlaceService;
 import com.xy.utils.*;
-import com.xy.utils.enums.DeviceActiveStateEnum;
-import com.xy.utils.enums.DeviceAuthCodeUseStatus;
-import com.xy.utils.enums.DeviceNetSateType;
-import com.xy.utils.enums.DictSonEnum;
+import com.xy.utils.enums.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -61,11 +59,14 @@ public class MercMiniDeviceController {
     private final DeviceInfoServiceImpl deviceInfoService;
 
     private final DeviceSysinfoServiceImpl deviceSysinfoService;
+
     private final MercPlaceService mercPlaceService;
+
     private final MercLineService mercLineService;
 
     private final DeviceBluetoothAuthServiceImpl deviceBluetoothAuthService;
 
+    private final DeviceChargingServiceImpl deviceChargingService;
 
     @ApiOperation("商户设备首页统计")
     @PostMapping("mercHomeStatistical")
@@ -75,6 +76,7 @@ public class MercMiniDeviceController {
         return deviceInfoService.mercHomeStatistical(dto);
     }
 
+
     @PostMapping("searchPage")
     @ApiOperation("小程序商户设备搜索")
     public R<PageBean<DeviceInfoDto.MerHomeSearchVO>> mercDeviceSearchPage(@RequestBody DeviceInfoDto.Page page) {
@@ -106,6 +108,16 @@ public class MercMiniDeviceController {
             vo.setDistrictName(CollUtil.isEmpty(districtMap) ? StrUtil.EMPTY : districtMap.get(districtId));
             DeviceStatusDto.Vo deviceStatus = vo.getDeviceStatus();
             vo.setNetStateName(deviceStatus == null ? StrUtil.EMPTY : DeviceNetSateType.getEnumByCode(deviceStatus.getNetState()).getDescription());
+
+            Integer deviceStateL = deviceStatus.getLockStateL();
+            Integer deviceStateR = deviceStatus.getLockStateR();
+            vo.setDeviceStateL(deviceStateL);
+            vo.setDeviceStateR(deviceStateR);
+            DeviceLockState deviceLockStateL = DeviceLockState.getEnumByCode(deviceStateL);
+            DeviceLockState deviceLockStateR = DeviceLockState.getEnumByCode(deviceStateR);
+            vo.setDeviceStateRName(deviceLockStateR == null ? "未知" : deviceLockStateR.getDescription());
+            vo.setDeviceStateLName(deviceLockStateL == null ? "未知" : deviceLockStateL.getDescription());
+
         }
         return R.ok(vo);
     }
@@ -117,7 +129,7 @@ public class MercMiniDeviceController {
         return deviceInfoService.dataCount(dto);
     }
 
-    private R checkDeviceByMerc(DeviceInfo deviceInfo){
+    private R checkDeviceByMerc(DeviceInfo deviceInfo) {
         Long mercId = MercAuthUtils.getMercId();
         //商户是否已通过审核
         MercDto.Vo mercInfo = mercFeignService.obj(new MercDto.ListDTO().setId(mercId)).getData();
@@ -125,7 +137,7 @@ public class MercMiniDeviceController {
             return R.fail("商户未通过审核");
         }
         //设备是否存在
-        if(!Emptys.check(deviceInfo)){
+        if (!Emptys.check(deviceInfo)) {
             return R.fail("机器不存在");
         }
         //机器是否已授权给该商户
@@ -141,7 +153,7 @@ public class MercMiniDeviceController {
 
     @PostMapping("isMerc")
     @ApiOperation("判断设备是否归属商户")
-    public R isMerc(@RequestBody MercMiniDeviceDto.Active active){
+    public R isMerc(@RequestBody MercMiniDeviceDto.Active active) {
         DeviceInfo deviceInfo = deviceInfoService.getById(active.getDeviceId());
         R checkR = this.checkDeviceByMerc(deviceInfo);
         if (checkR.getCode() == R.Enum.SUCCESS.getCode()) {
@@ -169,25 +181,39 @@ public class MercMiniDeviceController {
 
     @PostMapping("active")
     @ApiOperation("激活设备")
+    @Transactional(rollbackFor = Exception.class)
     public R active(@RequestBody MercMiniDeviceDto.Active active) {
         R activeInfo = this.getActiveInfo(active);
-        if(activeInfo.getCode() == R.Enum.SUCCESS.getCode()){
-            //激活设备
+        //激活设备
+        if (activeInfo.getCode() == R.Enum.SUCCESS.getCode()) {
+            LocalDateTime now = LocalDateTime.now();
             DeviceInfo updateDeviceInfo = new DeviceInfo()
                     .setDeviceId(active.getDeviceId())
                     .setActiveState(Integer.valueOf(DictSonEnum.DEVICE_ACTIVE_STATUS_1.getKey()))
                     .setBusyState(Integer.valueOf(DictSonEnum.DEVICE_BUSY_STATUS_1.getKey()))
-                    .setActiveTime(LocalDateTime.now())
+                    .setActiveTime(now)
                     .setShowStatus(true);
             deviceInfoService.updateById(updateDeviceInfo);
+            //首次激活可试用x天
+            DeviceCharging deviceCharging = deviceChargingService.getById(active.getDeviceId());
+            if (deviceCharging == null) {
+                SysDictRedis sysDictRedis = SysDictUtils.get(DictEnum.DEVICE_CHARGING.getKey(), DictSonEnum.DEVICE_CHARGING_X.getKey());
+                deviceChargingService.save(new DeviceCharging()
+                        .setDeviceId(active.getDeviceId())
+                        .setChargingX(Integer.valueOf(sysDictRedis.getValue()))
+                        .setTimeout(now)
+                        .setCreateTime(now)
+                );
+            }
             return R.ok();
-        }else{
+        } else {
             return activeInfo;
         }
     }
 
-    @PostMapping("modifyBusyStage")
     @ApiOperation("运营状态修改")
+    @PostMapping("modifyBusyStage")
+    @AliPay(AliPay.Type.BUSY_STATE)
     public R modifyBusyStage(@RequestBody @Validated MercMiniDeviceDto.BusySate busySate) {
         Long mercId = MercAuthUtils.getMercId();
         Long deviceId = busySate.getDeviceId();

+ 4 - 0
device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceHomePageController.java

@@ -36,6 +36,7 @@ public class MercMiniDeviceHomePageController {
     private DeviceDataServiceImpl deviceDataService;
     private OrderRefundService refundService;
 
+
     @PostMapping("count")
     @ApiOperation("首页统计")
     public R<MercMiniDeviceDto.HomePageVO> homepageCount() {
@@ -52,6 +53,7 @@ public class MercMiniDeviceHomePageController {
             //今日销售额 (扣除今日的订单的退款金额)
             day.setDayHisRefundMoney(hisRefundMoney);
             day.setDayRefundMoney(todayRefundMoney);
+            //改为和更多数据中的今日收益一样
             day.setSalesPrice(mercDataOneDay.stream().mapToInt(DeviceDataDto.Vo::getSalesMoney).sum() - todayRefundMoney);
             day.setOrderNum(mercDataOneDay.stream().mapToInt(DeviceDataDto.Vo::getSalesCount).sum());
             day.setRefundMoney(hisRefundMoney + todayRefundMoney);
@@ -73,4 +75,6 @@ public class MercMiniDeviceHomePageController {
         vo.setMonth(month);
         return R.ok(vo);
     }
+
+
 }

+ 7 - 2
device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceRecordsController.java

@@ -6,6 +6,7 @@ import com.xy.service.DeviceErrorsRecordService;
 import com.xy.service.DeviceNetRecordService;
 import com.xy.service.DeviceRecordsService;
 import com.xy.service.DeviceTempRecordsService;
+import com.xy.utils.Emptys;
 import com.xy.utils.MercAuthUtils;
 import com.xy.utils.PageBean;
 import com.xy.utils.R;
@@ -67,8 +68,12 @@ public class MercMiniDeviceRecordsController {
     @ApiOperation("设备详情首页-联网记录")
     @PostMapping("indexDeviceNetRecords")
     public R<List<DeviceNetRecordDto.Vo>> indexDeviceNetRecords(@RequestBody @Validated MiniDeviceRecordsDto.DeviceIdDto dto) {
-        DeviceNetRecordDto.Page page = (DeviceNetRecordDto.Page) new DeviceNetRecordDto.Page().setMercId(MercAuthUtils.getMercId())
-                .setDeviceId(dto.getDeviceId());
+        DeviceNetRecordDto.Page page =
+                (DeviceNetRecordDto.Page) new DeviceNetRecordDto.Page()
+                        .setMercId(MercAuthUtils.getMercId());
+        if(Emptys.check(dto.getDeviceId())){
+            page.setDeviceId(dto.getDeviceId());
+        }
         page.setPage(getPageBean(INDEX_RECORDS_COUNT));
         List<DeviceNetRecordDto.Vo> recordsList = deviceNetRecordPage(page).getData().getRecords();
         return R.ok(recordsList);

+ 0 - 2
device-api-service-merc-mini/src/main/java/com/xy/dto/MiniDeviceRecordsDto.java

@@ -30,11 +30,9 @@ public class MiniDeviceRecordsDto {
     @Accessors(chain = true)
     public static class DeviceErrorPageDto{
         @ApiModelProperty("设备ID")
-        @NotNull(message = "设备ID不能为空")
         private Long deviceId;
 
         @ApiModelProperty("故障类型")
-        @NotNull(message = "故障类型不能为空")
         private Integer errorType;
     }
 }

+ 10 - 3
device-api-service/pom.xml

@@ -39,13 +39,16 @@
             <artifactId>goods-api</artifactId>
             <version>1.0</version>
         </dependency>
-
         <dependency>
             <groupId>com.xy</groupId>
             <artifactId>sys-api</artifactId>
             <version>1.0</version>
         </dependency>
-
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>merc-api</artifactId>
+            <version>1.0</version>
+        </dependency>
 
         <dependency>
             <groupId>com.xy</groupId>
@@ -84,6 +87,10 @@
             <version>1.0</version>
             <scope>compile</scope>
         </dependency>
-
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>xy-alipay</artifactId>
+            <version>1.0</version>
+        </dependency>
     </dependencies>
 </project>

+ 39 - 0
device-api-service/src/main/java/com/xy/alipay/AliPay.java

@@ -0,0 +1,39 @@
+package com.xy.alipay;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.lang.annotation.*;
+
+/**
+ * 支付宝注解
+ *
+ * @author lijin
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface AliPay {
+
+    /**
+     * 类型
+     *
+     * @return
+     */
+    Type value();
+
+
+    @Getter
+    @AllArgsConstructor
+    enum Type {
+
+        RESTART("重启设备"),
+
+        BUSY_STATE("修改运营状态")
+
+        ;
+
+        private String type;
+    }
+
+}

+ 141 - 0
device-api-service/src/main/java/com/xy/alipay/AliPayAspet.java

@@ -0,0 +1,141 @@
+package com.xy.alipay;
+
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.xy.collections.list.JArrayList;
+import com.xy.collections.map.JMap;
+import com.xy.dto.CommandMqtt;
+import com.xy.dto.DeviceChangeStatusDTO;
+import com.xy.dto.MercMiniDeviceDto;
+import com.xy.entity.DeviceInfo;
+import com.xy.service.AlipayDeviceService;
+import com.xy.service.DeviceInfoServiceImpl;
+import com.xy.utils.AuthorizeUtils;
+import com.xy.utils.R;
+import com.xy.utils.enums.DictSonEnum;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Aspect
+@Component
+@AllArgsConstructor
+public class AliPayAspet {
+
+    private DeviceInfoServiceImpl deviceInfoService;
+
+    private AlipayDeviceService alipayDeviceService;
+
+    /**
+     * 支付宝设备
+     *
+     * @param joinPoint
+     * @param aliPay
+     * @return
+     * @throws Throwable
+     */
+    @Around("@annotation(aliPay)")
+    public Object timer(ProceedingJoinPoint joinPoint, AliPay aliPay) throws Throwable {
+        String type = aliPay.value().getType();
+        Object[] args = joinPoint.getArgs();
+        Object result = R.ok();
+        try {
+            boolean fal = before(type, args);
+            if (fal) {
+                result = joinPoint.proceed(args);
+            }
+        } catch (Exception e) {
+            throw e;
+        }
+        return result;
+    }
+
+    public boolean before(String type, Object[] args) {
+        boolean fal = true;
+        //重启设备
+        if (type.equals(AliPay.Type.RESTART.getType())) {
+            List<CommandMqtt> restart = restart(args);
+            if (restart.size() > 0) {
+                args[0] = restart;
+            } else {
+                fal = false;
+            }
+        }
+        //修改运营状态
+        if (type.equals(AliPay.Type.BUSY_STATE.getType())) {
+            fal = busyState(args);
+        }
+        return fal;
+    }
+
+    /**
+     * 重启设备
+     *
+     * @param args
+     */
+    private List<CommandMqtt> restart(Object[] args) {
+        List<CommandMqtt> result = new ArrayList<>();
+        List<CommandMqtt> commandMqtts = (List<CommandMqtt>) args[0];
+        //查询支付宝设备信息
+        List<DeviceInfo> deviceInfos = deviceInfoService.list(new LambdaQueryWrapper<DeviceInfo>()
+                .in(DeviceInfo::getDeviceId, new JArrayList<>(commandMqtts).comparing(CommandMqtt::getDeviceId).getProperty(CommandMqtt::getDeviceId))
+                .eq(DeviceInfo::getDeviceType, DictSonEnum.DEVICE_TYPE_5.getKey())
+        );
+        if (deviceInfos.size() == 0) {
+            return commandMqtts;
+        }
+        JMap<Long, DeviceInfo> deviceInfosJMaps = new JArrayList<>(deviceInfos).toMap(DeviceInfo::getDeviceId).cover();
+        commandMqtts.forEach(commandMqtt -> {
+            JSONObject templet = commandMqtt.getTemplet();
+            JSONObject data = templet.getJSONObject("data");
+            DeviceInfo deviceInfo = deviceInfosJMaps.get(commandMqtt.getDeviceId());
+            if (deviceInfo == null) {
+                result.add(commandMqtt);
+                return;
+            }
+            //发送支付宝设备重启请求
+            if (data.getStr("type").equals("app") && data.getStr("task").equals("restart")) {
+                alipayDeviceService.deviceReboot(deviceInfo.getDistrictId().toString());
+            }
+        });
+        return result;
+    }
+
+    /**
+     * 修改运营状态
+     *
+     * @param args
+     * @return
+     */
+    private boolean busyState(Object[] args) {
+        MercMiniDeviceDto.BusySate busySate = (MercMiniDeviceDto.BusySate) args[0];
+        //查询支付宝设备信息
+        DeviceInfo deviceInfo = deviceInfoService.getOne(new LambdaQueryWrapper<DeviceInfo>()
+                .eq(DeviceInfo::getDeviceId, busySate.getDeviceId())
+                .eq(DeviceInfo::getDeviceType, DictSonEnum.DEVICE_TYPE_5.getKey())
+        );
+        if (deviceInfo == null) {
+            return true;
+        }
+        Long deviceId = busySate.getDeviceId();
+        DeviceInfo updateDeviceInfo = new DeviceInfo()
+                .setDeviceId(deviceId)
+                .setBusyState(busySate.getBusyState())
+                .setFreezeStatus(busySate.getBusyState());
+        deviceInfoService.updateById(updateDeviceInfo);
+        //发送支付宝设备修改运营状态请求
+        DeviceChangeStatusDTO deviceChangeStatusDTO = new DeviceChangeStatusDTO()
+                .setTerminalId(String.valueOf(deviceId))
+                .setOperatorId(AuthorizeUtils.getLoginId(String.class))
+                .setStatus(busySate.getBusyState());
+        alipayDeviceService.changeStatus(deviceChangeStatusDTO);
+        return false;
+    }
+}

+ 24 - 0
device-api-service/src/main/java/com/xy/consumer/connected/ConnectedMqttConfiguration.java

@@ -24,6 +24,30 @@ public class ConnectedMqttConfiguration {
      */
     public static final String CHANNEL_NAME_IN = TOPIC + "MqttInboundChannel";
 
+    /**
+     * 出站通道名(生产者)发布的bean名称
+     */
+    public static final String CHANNEL_NAME_OUT = TOPIC + "MqttOutboundChannel";
+
+    /*******************************生产者*******************************************/
+
+    /**
+     * MQTT信息通道(生产者)
+     */
+    @Bean(name = CHANNEL_NAME_OUT)
+    public MessageChannel mqttOutboundChannel() {
+        return new DirectChannel();
+    }
+
+    /**
+     * MQTT消息处理器(生产者)
+     */
+    @Bean(name = TOPIC + "MqttOutbound")
+    @ServiceActivator(inputChannel = CHANNEL_NAME_OUT)
+    public MessageHandler mqttOutbound() {
+        return MqttConfigUtils.mqttOutbound(TOPIC);
+    }
+
 
     /*******************************消费者*******************************************/
 

+ 26 - 0
device-api-service/src/main/java/com/xy/consumer/connected/ConnectedProducer.java

@@ -0,0 +1,26 @@
+package com.xy.consumer.connected;
+
+import org.springframework.integration.annotation.MessagingGateway;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+/**
+ * 生产者接口
+ */
+@Component
+@MessagingGateway(defaultRequestChannel = ConnectedMqttConfiguration.CHANNEL_NAME_OUT)
+public interface ConnectedProducer {
+
+    /**
+     * ata是发送消息的内容
+     * topic是消息发送的主题,就是配置文件的主题
+     * qos是mqtt 对消息处理机制分为0,1,2 其中0表示的是订阅者没收到消息不会再次发送,消息会丢失,1表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息,2相比多了一次去重的动作,确保订阅者收到的消息有一次
+     */
+
+    void sendToMqtt(String data);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos);
+}

+ 24 - 0
device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedMqttConfiguration.java

@@ -24,6 +24,30 @@ public class DisconnectedMqttConfiguration {
      */
     public static final String CHANNEL_NAME_IN = TOPIC + "MqttInboundChannel";
 
+    /**
+     * 出站通道名(生产者)发布的bean名称
+     */
+    public static final String CHANNEL_NAME_OUT = TOPIC + "MqttOutboundChannel";
+
+    /*******************************生产者*******************************************/
+
+    /**
+     * MQTT信息通道(生产者)
+     */
+    @Bean(name = CHANNEL_NAME_OUT)
+    public MessageChannel mqttOutboundChannel() {
+        return new DirectChannel();
+    }
+
+    /**
+     * MQTT消息处理器(生产者)
+     */
+    @Bean(name = TOPIC + "MqttOutbound")
+    @ServiceActivator(inputChannel = CHANNEL_NAME_OUT)
+    public MessageHandler mqttOutbound() {
+        return MqttConfigUtils.mqttOutbound(TOPIC);
+    }
+
 
     /*******************************消费者*******************************************/
 

+ 26 - 0
device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedProducer.java

@@ -0,0 +1,26 @@
+package com.xy.consumer.disconnect;
+
+import org.springframework.integration.annotation.MessagingGateway;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+/**
+ * 生产者接口
+ */
+@Component
+@MessagingGateway(defaultRequestChannel = DisconnectedMqttConfiguration.CHANNEL_NAME_OUT)
+public interface DisconnectedProducer {
+
+    /**
+     * ata是发送消息的内容
+     * topic是消息发送的主题,就是配置文件的主题
+     * qos是mqtt 对消息处理机制分为0,1,2 其中0表示的是订阅者没收到消息不会再次发送,消息会丢失,1表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息,2相比多了一次去重的动作,确保订阅者收到的消息有一次
+     */
+
+    void sendToMqtt(String data);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos);
+}

+ 45 - 0
device-api-service/src/main/java/com/xy/entity/DeviceCharging.java

@@ -0,0 +1,45 @@
+package com.xy.entity;
+
+import java.time.LocalDateTime;
+import java.io.Serializable;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 设备计费表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="DeviceCharging对象", description="设备计费表")
+public class DeviceCharging implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId
+    @ApiModelProperty(value = "设备id")
+    private Long deviceId;
+
+    @ApiModelProperty(value = "累计续费金额")
+    private Integer chargingSumMoney;
+
+    @ApiModelProperty(value = "试用剩余天")
+    private Integer chargingX;
+
+    @ApiModelProperty(value = "过期时间")
+    private LocalDateTime timeout;
+
+    @ApiModelProperty(value = "创建时间")
+    private LocalDateTime createTime;
+
+}

+ 44 - 0
device-api-service/src/main/java/com/xy/entity/DeviceChargingHistory.java

@@ -0,0 +1,44 @@
+package com.xy.entity;
+
+import com.xy.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 设备计费历史表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "DeviceChargingHistory对象", description = "设备计费历史表")
+public class DeviceChargingHistory extends BaseEntity<DeviceChargingHistory> implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "设备id")
+    private Long deviceId;
+
+    @ApiModelProperty(value = "续费金额")
+    private Integer chargingMoney;
+
+    @ApiModelProperty(value = "续费方式")
+    private Integer chargingType;
+
+    @ApiModelProperty(value = "续费有效期")
+    private LocalDateTime chargingDateTime;
+
+    @ApiModelProperty(value = "创建时间")
+    private LocalDateTime createTime;
+
+}

+ 3 - 13
device-api-service/src/main/java/com/xy/entity/DeviceErrorsRecord.java

@@ -22,7 +22,7 @@ import java.time.LocalDateTime;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
-@ApiModel(value="DeviceErrorsRecord对象", description="机器-故障表")
+@ApiModel(value = "DeviceErrorsRecord对象", description = "机器-故障表")
 public class DeviceErrorsRecord implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -37,20 +37,10 @@ public class DeviceErrorsRecord implements Serializable {
     @ApiModelProperty(value = "设备编号")
     private Long deviceId;
 
-    @ApiModelProperty(value = "故障类型")
-    private Integer errorType;
-
-    @ApiModelProperty(value = "故障描述")
-    private String errorDescript;
-
-    @ApiModelProperty(value = "上位机版本号")
-    private String appUpmVersion;
-
-    @ApiModelProperty(value = "下位机版本号")
-    private String appDownmVersion;
+    @ApiModelProperty(value = "故障编码")
+    private String code;
 
     @ApiModelProperty(value = "创建时间")
     private LocalDateTime createTime;
 
-
 }

+ 171 - 0
device-api-service/src/main/java/com/xy/job/DeviceChargingJob.java

@@ -0,0 +1,171 @@
+package com.xy.job;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.xy.collections.list.JArrayList;
+import com.xy.collections.list.JList;
+import com.xy.collections.map.JMap;
+import com.xy.dto.DeviceInfoDto;
+import com.xy.dto.MercAccountDto;
+import com.xy.entity.DeviceCharging;
+import com.xy.entity.DeviceChargingHistory;
+import com.xy.entity.DeviceInfo;
+import com.xy.entity.SysDictRedis;
+import com.xy.mapper.DeviceChargingMapper;
+import com.xy.service.DeviceChargingHistoryServiceImpl;
+import com.xy.service.DeviceChargingServiceImpl;
+import com.xy.service.DeviceInfoServiceImpl;
+import com.xy.service.MercAccountService;
+import com.xy.utils.*;
+import com.xy.utils.enums.DictEnum;
+import com.xy.utils.enums.DictSonEnum;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 设备计费job
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class DeviceChargingJob {
+
+    private DeviceChargingServiceImpl deviceChargingService;
+
+    private DeviceChargingHistoryServiceImpl deviceChargingHistoryService;
+
+    private DeviceInfoServiceImpl deviceInfoService;
+
+    private MercAccountService mercAccountService;
+
+    private DeviceChargingMapper deviceChargingMapper;
+
+    /**
+     * 扣除设备服务费试用天数
+     *
+     * @return
+     */
+    @XxlJob("deviceChargingX")
+    public ReturnT<String> deviceChargingX() {
+        deviceChargingMapper.updateChargingX();
+        log.info("设备试用时间扣除完成~");
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 设备计费
+     *
+     * @return
+     */
+    @XxlJob("deviceCharging")
+    public ReturnT<String> deviceCharging() {
+        deviceCharging(1, 20, null);
+        log.info("设备计费完成~");
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 递归执行
+     *
+     * @param current
+     * @param size
+     * @param deviceIds
+     */
+    public void deviceCharging(int current, int size, List<Long> deviceIds) {
+        log.info("设备计费开始第{}页", current);
+        List<DeviceCharging> updateDeviceChargings = new ArrayList<>();
+        List<DeviceChargingHistory> deviceChargingHistories = new ArrayList<>();
+        List<DeviceInfoDto.Update> updateDeviceInfos = new ArrayList<>();
+        LocalDateTime now = LocalDateTime.now();
+        //查询已过期计费记录
+        PageBean<DeviceCharging> pageBean = new PageBean().setCurrent(current).setSize(size);
+        IPage<DeviceCharging> iPage = deviceChargingService.page(PlusBeans.toIPage(pageBean), new LambdaQueryWrapper<DeviceCharging>()
+                .le(DeviceCharging::getTimeout, now)
+                .in(Emptys.check(deviceIds), DeviceCharging::getDeviceId, deviceIds)
+        );
+        List<DeviceCharging> records = iPage.getRecords();
+        if (!Emptys.check(records)) {
+            return;
+        }
+        //查询设备信息
+        JList<DeviceCharging> deviceChargings = new JArrayList<>(records);
+        JMap<Long, DeviceCharging> deviceChargingsJMaps = deviceChargings.toMap(DeviceCharging::getDeviceId).cover();
+        List<DeviceInfo> deviceInfos = deviceInfoService.list(new LambdaQueryWrapper<DeviceInfo>()
+                .in(DeviceInfo::getDeviceId, deviceChargings.getProperty(DeviceCharging::getDeviceId))
+        );
+        JMap<Long, DeviceInfo> deviceInfosJMaps = new JArrayList<>(deviceInfos).toMap(DeviceInfo::getDeviceId).cover();
+        //字典
+        Map<String, SysDictRedis> stringSysDictRedisMap = SysDictUtils.get(DictEnum.DEVICE_CHARGING.getKey());
+        SysDictRedis sysDictRedisY = stringSysDictRedisMap.get(DictSonEnum.DEVICE_CHARGING_Y.getKey());
+        Integer y = Integer.valueOf(sysDictRedisY.getValue());
+        //开始计费
+        deviceChargingsJMaps.forEach((deviceId, deviceCharging) -> {
+            //发起扣款
+            DeviceInfo deviceInfo = deviceInfosJMaps.get(deviceId);
+            if (deviceInfo.getMercId() == -1) {
+                return;
+            }
+            SysDictRedis sysDictRedisBalance = stringSysDictRedisMap.get(String.valueOf(deviceInfo.getDeviceType()));
+            Integer balance = Integer.valueOf(sysDictRedisBalance.getValue());
+            R r = mercAccountService.updateBalance(new MercAccountDto.UpdateBalance()
+                    .setMercId(deviceInfo.getMercId())
+                    .setBalance(balance)
+                    .setResean("设备管理费")
+            );
+            //扣款成功
+            if (r.getCode() == R.Enum.SUCCESS.getCode()) {
+                LocalDateTime newTimeOut = DataTime.toLocal(DataTime.getStringAround(1, 0, 0, 0, 0, 0, DataTime.toString(deviceCharging.getTimeout())));
+                deviceCharging.setChargingSumMoney(deviceCharging.getChargingSumMoney() + balance)
+                        .setTimeout(newTimeOut);
+                DeviceChargingHistory deviceChargingHistory = new DeviceChargingHistory()
+                        .createId()
+                        .setDeviceId(deviceId)
+                        .setChargingMoney(balance)
+                        .setChargingType(DictSonEnum.DEVICE_CHARGING_100.getKeyInt())
+                        .setChargingDateTime(newTimeOut)
+                        .setCreateTime(now);
+                deviceChargingHistories.add(deviceChargingHistory);
+            }
+            //扣款失败
+            if (r.getCode() == R.Enum.FAIL.getCode()) {
+                //当前时间 - 过期时间 > y && 试用期 <= 0 则冻结设备
+                long day = DataTime.diff(now, deviceCharging.getTimeout(), "d");
+                if (day > y && deviceCharging.getChargingX() <= 0) {
+                    DeviceInfoDto.Update update = new DeviceInfoDto.Update()
+                            .setDeviceId(deviceId);
+                    update.setFreezeStatus(2);
+                    updateDeviceInfos.add(update);
+                }
+            }
+            updateDeviceChargings.add(deviceCharging);
+        });
+        //修改设备计费记录
+        if (Emptys.check(updateDeviceChargings)) {
+            deviceChargingService.updateBatchById(updateDeviceChargings);
+        }
+        //添加设备计费记录历史
+        if (Emptys.check(deviceChargingHistories)) {
+            deviceChargingHistoryService.saveBatch(deviceChargingHistories);
+        }
+        //冻结设备
+        if (Emptys.check(updateDeviceInfos)) {
+            deviceInfoService.updateBatch(updateDeviceInfos);
+        }
+
+        //判断是否继续下一页
+        if (iPage.getPages() <= current) {
+            return;
+        } else {
+            deviceCharging(current + 1, size, deviceIds);
+        }
+    }
+
+}

+ 16 - 0
device-api-service/src/main/java/com/xy/mapper/DeviceChargingHistoryMapper.java

@@ -0,0 +1,16 @@
+package com.xy.mapper;
+
+import com.xy.entity.DeviceChargingHistory;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 设备计费历史表 Mapper 接口
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public interface DeviceChargingHistoryMapper extends BaseMapper<DeviceChargingHistory> {
+
+}

+ 36 - 0
device-api-service/src/main/java/com/xy/mapper/DeviceChargingMapper.java

@@ -0,0 +1,36 @@
+package com.xy.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.xy.dto.DeviceChargingDto;
+import com.xy.entity.DeviceCharging;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * <p>
+ * 设备计费表 Mapper 接口
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public interface DeviceChargingMapper extends BaseMapper<DeviceCharging> {
+
+    /**
+     * 扣除设备服务费试用天数
+     *
+     * @return
+     */
+    @Select("update device_charging set charging_x = charging_x - 1 where charging_x > 0")
+    int updateChargingX();
+
+    /**
+     * 分页查询
+     *
+     * @param page
+     * @param queryPage
+     * @return
+     */
+    IPage<DeviceChargingDto.PageVo> page(IPage page, @Param("queryPage") DeviceChargingDto.Page queryPage);
+}

+ 10 - 1
device-api-service/src/main/java/com/xy/mapper/DeviceDataMapper.java

@@ -1,7 +1,11 @@
 package com.xy.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xy.dto.DeviceDataDto;
 import com.xy.entity.DeviceData;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,5 +17,10 @@ import com.xy.entity.DeviceData;
  */
 public interface DeviceDataMapper extends BaseMapper<DeviceData> {
 
- 
+
+    List<DeviceDataDto.DayChartVo> dayChart(@Param("mercId") Long mercId
+            , @Param("beginDateInt") Integer beginDateInt
+            , @Param("endDateInt") Integer endDateInt
+            , @Param("type") String type
+    );
 }

+ 1 - 0
device-api-service/src/main/java/com/xy/mapper/DeviceInfoMapper.java

@@ -35,4 +35,5 @@ public interface DeviceInfoMapper extends BaseMapper<DeviceInfo> {
      * @return
      */
     List<DeviceInfoDto.MercHomeCountVO> merHomeCountList(@Param("query") DeviceInfoDto.MercHomeQueryDTO queryDTO);
+
 }

+ 18 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingHistoryMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xy.mapper.DeviceChargingHistoryMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.DeviceChargingHistory">
+        <id column="id" property="id" />
+        <result column="device_id" property="deviceId" />
+        <result column="device_type" property="deviceType" />
+        <result column="charging_money" property="chargingMoney" />
+        <result column="charging_sum_money" property="chargingSumMoney" />
+        <result column="charging_type" property="chargingType" />
+        <result column="status" property="status" />
+        <result column="timeout" property="timeout" />
+        <result column="create_time" property="createTime" />
+    </resultMap>
+
+</mapper>

+ 18 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xy.mapper.DeviceChargingMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.DeviceCharging">
+        <id column="device_id" property="deviceId" />
+        <result column="device_type" property="deviceType" />
+        <result column="charging_money" property="chargingMoney" />
+        <result column="charging_sum_money" property="chargingSumMoney" />
+        <result column="charging_type" property="chargingType" />
+        <result column="status" property="status" />
+        <result column="timeout" property="timeout" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+</mapper>

+ 57 - 0
device-api-service/src/main/java/com/xy/service/DeviceChargingHistoryServiceImpl.java

@@ -0,0 +1,57 @@
+package com.xy.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.dto.DeviceChargingHistoryDto;
+import com.xy.dto.DeviceInfoDto;
+import com.xy.entity.DeviceChargingHistory;
+import com.xy.mapper.DeviceChargingHistoryMapper;
+import com.xy.utils.Emptys;
+import com.xy.utils.PageBean;
+import com.xy.utils.PlusBeans;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+import static com.xy.utils.PlusBeans.toPageBean;
+
+/**
+ * <p>
+ * 设备计费历史表 服务实现类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "设备计费历史表")
+public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceChargingHistoryMapper, DeviceChargingHistory> implements DeviceChargingHistoryService {
+
+    private DeviceInfoServiceImpl deviceInfoService;
+
+    @PostMapping("page")
+    @ApiOperation("分页查询")
+    public R<PageBean<DeviceChargingHistoryDto.PageVo>> page(@RequestBody @Validated DeviceChargingHistoryDto.Page page) {
+        //查询设备计费历史
+        LambdaQueryWrapper<DeviceChargingHistory> lambdaQueryWrapper = new LambdaQueryWrapper<DeviceChargingHistory>().eq(DeviceChargingHistory::getDeviceId, page.getDeviceId());
+        IPage<DeviceChargingHistory> iPage = page(PlusBeans.toIPage(page.getPage()), lambdaQueryWrapper);
+        PageBean<DeviceChargingHistoryDto.PageVo> pageVoPageBean = toPageBean(DeviceChargingHistoryDto.PageVo.class, iPage);
+        List<DeviceChargingHistoryDto.PageVo> records = pageVoPageBean.getRecords();
+        if (!Emptys.check(records)) {
+            return R.ok(pageVoPageBean);
+        }
+        //查询设备信息
+        DeviceInfoDto.Vo deviceInfo = deviceInfoService.obj(new DeviceInfoDto.Obj().setDeviceId(page.getDeviceId())).getData();
+        records.forEach(pageVo -> pageVo.setDeviceInfo(deviceInfo));
+        return R.ok(pageVoPageBean);
+    }
+}

+ 89 - 0
device-api-service/src/main/java/com/xy/service/DeviceChargingServiceImpl.java

@@ -0,0 +1,89 @@
+package com.xy.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.dto.DeviceChargingDto;
+import com.xy.dto.DeviceChargingHistoryDto;
+import com.xy.dto.DeviceInfoDto;
+import com.xy.entity.DeviceCharging;
+import com.xy.entity.DeviceChargingHistory;
+import com.xy.entity.SysDictRedis;
+import com.xy.job.DeviceChargingJob;
+import com.xy.mapper.DeviceChargingMapper;
+import com.xy.utils.*;
+import com.xy.utils.enums.DictEnum;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+import java.util.Map;
+
+import static com.xy.utils.PlusBeans.*;
+
+
+/**
+ * <p>
+ * 设备计费表 服务实现类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Service
+@Api(tags = "设备计费表")
+@AllArgsConstructor(onConstructor_ = @Lazy)
+public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper, DeviceCharging> implements DeviceChargingService {
+
+    private DeviceChargingJob deviceChargingJob;
+
+    private DeviceChargingHistoryServiceImpl deviceChargingHistoryService;
+
+    @PostMapping("charging")
+    @ApiOperation("手动计费")
+    public R charging(@RequestBody @Validated DeviceChargingDto.Charging charging) {
+        List<Long> deviceIds = charging.getDeviceIds();
+        deviceChargingJob.deviceCharging(1, deviceIds.size(), deviceIds);
+        return R.ok();
+    }
+
+    @PostMapping("page")
+    @ApiOperation("分页查询")
+    public R<PageBean<DeviceChargingDto.PageVo>> page(@RequestBody DeviceChargingDto.Page page) {
+        IPage<DeviceChargingDto.PageVo> iPage = baseMapper.page(toIPage(page.getPage()), page);
+        List<DeviceChargingDto.PageVo> records = iPage.getRecords();
+        if (Emptys.check(records)) {
+            Map<String, SysDictRedis> stringSysDictRedisMap = SysDictUtils.get(DictEnum.DEVICE_CHARGING.getKey());
+            for (DeviceChargingDto.PageVo record : records) {
+                DeviceInfoDto.Vo deviceInfo = record.getDeviceInfo();
+                //封装最新计费历史信息
+                LambdaQueryWrapper<DeviceChargingHistory> lambdaQueryWrapper = new LambdaQueryWrapper<DeviceChargingHistory>()
+                        .eq(DeviceChargingHistory::getDeviceId, deviceInfo.getDeviceId())
+                        .orderByDesc(DeviceChargingHistory::getCreateTime)
+                        .last("limit 1");
+                DeviceChargingHistory deviceChargingHistory = deviceChargingHistoryService.getOne(lambdaQueryWrapper);
+                if (deviceChargingHistory != null) {
+                    record.setDeviceChargingHistory(copy(DeviceChargingHistoryDto.Vo.class, deviceChargingHistory));
+                }
+                //封装计费标准金额
+                SysDictRedis sysDictRedis = stringSysDictRedisMap.get(deviceInfo.getDeviceType().toString());
+                if (sysDictRedis != null) {
+                    record.setChargingMoney(Integer.valueOf(sysDictRedis.getValue()));
+                }
+                //封装缴费状态
+                DeviceChargingDto.Vo deviceCharging = record.getDeviceCharging();
+                if (deviceCharging != null) {
+                    int contrast = DataTime.stringContrast(DataTime.toString(page.getThisTime()), DataTime.toString(deviceCharging.getTimeout()));
+                    record.setChargingStatus(contrast < 0);
+                }
+            }
+        }
+        return R.ok(toPageBean(iPage));
+    }
+}

+ 2 - 2
device-api-service/src/main/java/com/xy/service/DeviceCreateIdsServiceImpl.java

@@ -58,7 +58,7 @@ public class DeviceCreateIdsServiceImpl extends ServiceImpl<DeviceCreateIdsMappe
     @PostMapping("save")
     @ApiOperation("添加")
     @Lock("device-create-ids-save")
-    public R save(@RequestBody @Validated DeviceCreateIdsDto.Save save) {
+    public R<JList<DeviceCreateIds>> save(@RequestBody @Validated DeviceCreateIdsDto.Save save) {
         LocalDate localDate = LocalDate.now();
         String year = String.valueOf(localDate.getYear());
         String month = String.valueOf(localDate.getMonthValue());
@@ -94,7 +94,7 @@ public class DeviceCreateIdsServiceImpl extends ServiceImpl<DeviceCreateIdsMappe
         ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, partition.size());
         partition.forEach(createIds -> execute.execute(() -> saveBatch(createIds)));
         execute.end();
-        return R.ok();
+        return R.ok(deviceCreateIdss);
     }
 
     @PostMapping("page")

+ 43 - 0
device-api-service/src/main/java/com/xy/service/DeviceDataServiceImpl.java

@@ -1,6 +1,7 @@
 package com.xy.service;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -27,7 +28,9 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 
 import javax.validation.Valid;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -285,6 +288,46 @@ public class DeviceDataServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceD
         return copy(DeviceDataDto.Vo.class, list);
     }
 
+    @Override
+    public R<List<DeviceDataDto.Vo>> getMercDataOneDay(DeviceDataDto.CountByDay dto) {
+        return R.ok(this.getMercDataOneDay(dto.getMercId(), dto.getDateValue()));
+    }
+
+    @Override
+    public R<List<DeviceDataDto.Vo>> getMercDataOneMonth(DeviceDataDto.CountByMonth dto) {
+        return R.ok(this.getMercDataOneMonth(dto.getMercId(), dto.getDateValue()));
+    }
+
+    @ApiOperation("图表数据")
+    @Override
+    public R<List<DeviceDataDto.DayChartVo>> dayChart(@RequestBody @Valid DeviceDataDto.DayChartDto dto) {
+        List<DeviceDataDto.DayChartVo> dayChartVos = baseMapper.dayChart(dto.getMercId(), dto.getBeginInt(), dto.getEndDateInt(),dto.getType());
+        Map<Integer, DeviceDataDto.DayChartVo> voMap = dayChartVos.stream().collect(Collectors.toMap(DeviceDataDto.DayChartVo::getTime, i -> i));
+        List<String> dayList = DataTime.getBetweenDates(dto.getBeginDate().toString(), dto.getEndDate().toString(), true);
+        List<Integer> dayList2 = dayList.stream().map(i -> Integer.valueOf(StrUtil.replace(i, "-", ""))).collect(Collectors.toList());
+        List<DeviceDataDto.DayChartVo> list = new ArrayList<>();
+        dayList2.forEach(
+                i -> {
+                    Integer num = 0;
+                    Integer totalMoney = 0;
+                    BigDecimal totalMoneyYuan = new BigDecimal(0);
+                    DeviceDataDto.DayChartVo dayChartVo = voMap.get(i);
+                    if (Emptys.check(dayChartVo)) {
+                        num = dayChartVo.getNum();
+                        totalMoney = dayChartVo.getTotalMoney();
+                        totalMoneyYuan = dayChartVo.getTotalMoneyYuan();
+                    }
+                    list.add(new DeviceDataDto.DayChartVo()
+                            .setTime(i)
+                            .setNum(num)
+                            .setTotalMoney(totalMoney)
+                            .setTotalMoneyYuan(totalMoneyYuan)
+                    );
+                }
+        );
+        return R.ok(list);
+    }
+
     public static class SaveOrAccum {
 
         public R saveOrAccum(DeviceDataDto.SaveOrAccum saveOrAccum, DeviceDataServiceImpl deviceDataService) {

+ 24 - 10
device-api-service/src/main/java/com/xy/service/DeviceErrorsRecordServiceImpl.java

@@ -5,13 +5,12 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xy.dto.DeviceErrorsRecordDto;
 import com.xy.dto.DeviceInfoDto;
-import com.xy.dto.DeviceSysinfoDto;
 import com.xy.entity.DeviceErrorsRecord;
+import com.xy.entity.DeviceInfo;
+import com.xy.entity.SysCodeConfigureRedis;
 import com.xy.mapper.DeviceErrorsRecordMapper;
-import com.xy.utils.Emptys;
-import com.xy.utils.MybatisPlusQuery;
-import com.xy.utils.PageBean;
-import com.xy.utils.R;
+import com.xy.utils.*;
+import com.xy.utils.enums.SysCodeConfigureEnum;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
@@ -22,6 +21,8 @@ import org.springframework.web.bind.annotation.RequestBody;
 
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static com.xy.utils.Beans.copy;
 import static com.xy.utils.PlusBeans.toIPage;
@@ -49,13 +50,19 @@ public class DeviceErrorsRecordServiceImpl extends ServiceImpl<DeviceErrorsRecor
         if (deviceInfo == null) {
             return R.fail("设备不存在");
         }
-        DeviceSysinfoDto.Vo deviceSysinfo = deviceInfo.getDeviceSysinfo();
+        //添加故障记录
         save.setMercId(deviceInfo.getMercId());
-        save.setAppUpmVersion(deviceSysinfo.getAppUpmVersion());
-        save.setAppDownmVersion(deviceSysinfo.getAppDownmVersion());
         DeviceErrorsRecord deviceErrorsRecord = copy(DeviceErrorsRecord.class, save)
                 .setCreateTime(LocalDateTime.now());
         save(deviceErrorsRecord);
+        SysCodeConfigureRedis sysCodeConfigureRedis = SysCodeConfigureUtils.get(SysCodeConfigureEnum.D01.getCode(), save.getCode());
+        //修改设备当前故障等级
+        if (Emptys.check(sysCodeConfigureRedis.getExpand())) {
+            DeviceInfo updateDeviceInfo = new DeviceInfo()
+                    .setDeviceId(deviceInfo.getDeviceId())
+                    .setFaultLevel(Integer.valueOf(sysCodeConfigureRedis.getExpand()));
+            deviceInfoService.updateById(updateDeviceInfo);
+        }
         return R.ok();
     }
 
@@ -67,9 +74,16 @@ public class DeviceErrorsRecordServiceImpl extends ServiceImpl<DeviceErrorsRecor
                 .ge(DeviceErrorsRecord::getCreateTime, page.getBeginCreateTime())
                 .le(DeviceErrorsRecord::getCreateTime, page.getEndCreateTime())
                 .build()
-                .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceErrorsRecord::getCreateTime);
+                .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceErrorsRecord::getId);
         IPage<DeviceErrorsRecord> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
-        return R.ok(toPageBean(DeviceErrorsRecordDto.Vo.class, iPage));
+        PageBean<DeviceErrorsRecordDto.Vo> voPageBean = toPageBean(DeviceErrorsRecordDto.Vo.class, iPage);
+        //反显设备名称
+        if (Emptys.check(voPageBean.getRecords())) {
+            List<Long> deviceIdList = voPageBean.getRecords().stream().map(DeviceErrorsRecordDto.Vo::getDeviceId).collect(Collectors.toList());
+            Map<Long, String> deviceMap = deviceInfoService.getDeviceNameList(new DeviceInfoDto.DeviceIdDto().setDeviceId(deviceIdList)).getData();
+            voPageBean.getRecords().forEach(i -> i.setDeviceName(deviceMap.get(i.getDeviceId())));
+        }
+        return R.ok(voPageBean);
     }
 
     @PostMapping("list")

+ 54 - 35
device-api-service/src/main/java/com/xy/service/DeviceInfoServiceImpl.java

@@ -6,6 +6,7 @@ import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.text.StrBuilder;
 import cn.hutool.core.util.BooleanUtil;
 import cn.hutool.core.util.NumberUtil;
@@ -28,10 +29,7 @@ import com.xy.mapper.DeviceInfoMapper;
 import com.xy.mapper.entity.DeviceInfoQueryPage;
 import com.xy.util.ExcelUtils;
 import com.xy.utils.*;
-import com.xy.utils.enums.DeviceActiveStateEnum;
-import com.xy.utils.enums.DeviceNetSateType;
-import com.xy.utils.enums.DictEnum;
-import com.xy.utils.enums.DictSonEnum;
+import com.xy.utils.enums.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import jodd.introspector.MapperFunction;
@@ -221,7 +219,8 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @ApiOperation("修改")
     @PostMapping("update")
     public R update(@RequestBody @Validated DeviceInfoDto.Update update) {
-        DeviceInfo deviceInfo = copy(DeviceInfo.class, update);
+        DeviceInfo deviceInfo = copy(DeviceInfo.class, update)
+                .setUpdateTime(LocalDateTime.now());
         updateById(deviceInfo);
         return R.ok();
     }
@@ -229,8 +228,9 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @ApiOperation("批量修改")
     @PostMapping("updateBatch")
     public R updateBatch(@RequestBody List<DeviceInfoDto.Update> updates) {
+        LocalDateTime now = LocalDateTime.now();
         List<DeviceInfo> deviceInfos = new ArrayList<>(updates.size());
-        updates.forEach(update -> deviceInfos.add(copy(DeviceInfo.class, update)));
+        updates.forEach(update -> deviceInfos.add(copy(DeviceInfo.class, update).setUpdateTime(now)));
         updateBatchById(deviceInfos);
         return R.ok();
     }
@@ -531,20 +531,16 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         mercHomeStatisticalVO.setOnlineNum(onlineNum);
         mercHomeStatisticalVO.setOfflineNum(offlineNum);
 
-
-        //运营、停业
-        Map<Integer, Long> countBusyStateMap = mercDevices.stream().collect(Collectors
-                .groupingBy(DeviceInfo::getBusyState, Collectors.counting()));
-        Integer busyState1 = SysDictUtils.getValue(DictEnum.DEVICE_BUSY_STATUS.getKey(), DictSonEnum.DEVICE_BUSY_STATUS1.getKey(), Integer.class);
-        Integer busyState2 = SysDictUtils.getValue(DictEnum.DEVICE_BUSY_STATUS.getKey(), DictSonEnum.DEVICE_BUSY_STATUS2.getKey(), Integer.class);
-        int operatingNum = countBusyStateMap.get(busyState1) == null ? 0 : countBusyStateMap.get(busyState1).intValue();
-        int closedNum = countBusyStateMap.get(busyState2) == null ? 0 : countBusyStateMap.get(busyState2).intValue();
-        mercHomeStatisticalVO.setOperatingNum(operatingNum);
-        mercHomeStatisticalVO.setClosedNum(closedNum);
-
+        //锁机、未锁机
+        Map<Integer, Long> countLockLstateMap = deviceStatuses.stream().collect(Collectors
+                .groupingBy(DeviceStatus::getLockStateL, Collectors.counting()));
+        Long lockLStateNum = countLockLstateMap.get(DeviceLockState.LOCK.getCode());
+        Long unLockLStateNum = countLockLstateMap.get(DeviceLockState.UN_LOCK.getCode());
+        mercHomeStatisticalVO.setOperatingNum(unLockLStateNum == null ? 0 : unLockLStateNum.intValue());
+        mercHomeStatisticalVO.setClosedNum(lockLStateNum == null ? 0 : lockLStateNum.intValue());
         //待补货
-        //TODO: 此逻辑需要确认
-
+        Integer deviceNum = R.feignCheckData(goodsDeviceService.countOutOfStockDevice(new GoodsDeviceDto.CountOutOfStockDevice().setMercId(mercId)));
+        mercHomeStatisticalVO.setNeedToFillNum(deviceNum);
         return R.ok(mercHomeStatisticalVO);
     }
 
@@ -636,6 +632,15 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                     device.setNetStateName(DeviceNetSateType.getEnumByCode(deviceStatus.getNetState()).getDescription());
                 }
 
+                Integer deviceStateL = deviceStatus.getLockStateL();
+                Integer deviceStateR = deviceStatus.getLockStateR();
+                device.setDeviceStateL(deviceStateL);
+                device.setDeviceStateR(deviceStateR);
+                DeviceLockState deviceLockStateL = DeviceLockState.getEnumByCode(deviceStateL);
+                DeviceLockState deviceLockStateR = DeviceLockState.getEnumByCode(deviceStateR);
+                device.setDeviceStateRName(deviceLockStateR == null ? "未知" : deviceLockStateR.getDescription());
+                device.setDeviceStateLName(deviceLockStateL == null ? "未知" : deviceLockStateL.getDescription());
+
             }
 
             //在线排序
@@ -673,7 +678,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         //小程序独有查询字段 缺货状态:stockStatus ,是否查故障设备:fault
         Boolean fault = page.getFault();
         Long mercId = page.getMercId();
-        List<Long> myDeviceIds = page.getDeviceIdList();
+        List<Long> myDeviceIds = page.getMyDeviceIds();
         if (CollUtil.isEmpty(myDeviceIds)) {
             //无设备
             return R.ok(pageData);
@@ -698,32 +703,46 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             return R.ok(pageData);
         }
         List<DeviceInfoDto.MerHomeSearchVO> merHomeSearchRecords = new ArrayList<>();
-        List<Long> deviceIds = records.stream().map(DeviceInfoDto.Vo2::getDeviceId).collect(Collectors.toList());
-        String type = SysDictUtils.getValue(DictEnum.DEVICE_DATA_TYPE.getKey(), DictSonEnum.DEVICE_DATA_TYPE_DAY.getKey(), String.class);
-        String todayDate = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
-        //查询当天
-        DeviceDataDto.ListDTO dto = new DeviceDataDto.ListDTO()
-                .setDeviceIds(deviceIds).setType(type).setDateValue(Integer.valueOf(todayDate)).setMercId(mercId);
+
         BeanUtil.copyProperties(pageBean, pageData);
-        List<DeviceDataDto.Vo> deviceDataList = deviceDataService.list(dto);
-        if (CollUtil.isNotEmpty(deviceDataList)) {
+        if (CollUtil.isNotEmpty(records)) {
+            List<Long> deviceIds = records.stream().map(DeviceInfoDto.Vo2::getDeviceId).collect(Collectors.toList());
+            String type = SysDictUtils.getValue(DictEnum.DEVICE_DATA_TYPE.getKey(), DictSonEnum.DEVICE_DATA_TYPE_DAY.getKey(), String.class);
+            String todayDate = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
+            //查询当天
+            DeviceDataDto.ListDTO dto = new DeviceDataDto.ListDTO()
+                    .setDeviceIds(deviceIds).setType(type).setDateValue(Integer.valueOf(todayDate)).setMercId(mercId);
+            List<DeviceDataDto.Vo> deviceDataList = deviceDataService.list(dto);
+            Map<Long, DeviceDataDto.Vo> dataMap = MapUtil.newHashMap();
             //统计数据反显
-            Map<Long, DeviceDataDto.Vo> dataMap = deviceDataList.stream().collect(Collectors.toMap(DeviceDataDto.Vo::getDeviceId, d -> d));
-            records.forEach(v -> {
+            if (CollUtil.isNotEmpty(deviceDataList)) {
+                dataMap = deviceDataList.stream().collect(Collectors.toMap(DeviceDataDto.Vo::getDeviceId, d -> d));
+            }
+            for (DeviceInfoDto.Vo2 v : records) {
                 DeviceInfoDto.MerHomeSearchVO merHomeSearchVO = new DeviceInfoDto.MerHomeSearchVO();
                 Long deviceId = v.getDeviceId();
                 DeviceDataDto.Vo vo = dataMap.get(deviceId);
-                //今日订单数
-                v.setDayOrderNum(vo != null ? vo.getSalesCount() : 0);
-                v.setDaySalesPrice(vo != null ? vo.getSalesMoney() : 0);
+                if (vo != null) {
+                    //今日订单数
+                    v.setDayOrderNum(vo != null ? vo.getSalesCount() : 0);
+                    v.setDaySalesPrice(vo != null ? vo.getSalesMoney() : 0);
+                    BeanUtil.copyProperties(vo, merHomeSearchVO);
+                }
                 DeviceSysinfoDto.Vo deviceSysinfo = v.getDeviceSysinfo();
                 DeviceStatusDto.Vo deviceStatus = v.getDeviceStatus();
-                BeanUtil.copyProperties(vo, merHomeSearchVO);
                 merHomeSearchVO.setAppUpmVersion(deviceSysinfo.getAppUpmVersion());
                 merHomeSearchVO.setTempValue(deviceStatus.getTempValue());
                 merHomeSearchVO.setNetDbm(deviceStatus.getNetDbm());
+                Integer deviceStateL = deviceStatus.getLockStateL();
+                Integer deviceStateR = deviceStatus.getLockStateR();
+                merHomeSearchVO.setDeviceStateL(deviceStateL);
+                merHomeSearchVO.setDeviceStateR(deviceStateR);
+                DeviceLockState deviceLockStateL = DeviceLockState.getEnumByCode(deviceStateL);
+                DeviceLockState deviceLockStateR = DeviceLockState.getEnumByCode(deviceStateR);
+                merHomeSearchVO.setDeviceStateRName(deviceLockStateR == null ? "未知" : deviceLockStateR.getDescription());
+                merHomeSearchVO.setDeviceStateLName(deviceLockStateL == null ? "未知" : deviceLockStateL.getDescription());
                 merHomeSearchRecords.add(merHomeSearchVO);
-            });
+            }
             pageData.setRecords(merHomeSearchRecords);
         }
         return R.ok(pageData);

+ 99 - 0
device-api-service/src/main/java/com/xy/service/DeviceRegisterServiceImpl.java

@@ -1,5 +1,8 @@
 package com.xy.service;
 
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.read.listener.ReadListener;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -9,6 +12,8 @@ import com.xy.annotation.Lock;
 import com.xy.collections.list.JArrayList;
 import com.xy.collections.list.JList;
 import com.xy.collections.map.JMap;
+import com.xy.config.DeviceThreadPoolConfig;
+import com.xy.dto.DeviceCreateIdsDto;
 import com.xy.dto.DeviceQualityDto;
 import com.xy.dto.DeviceRegisterDto;
 import com.xy.dto.MqttUserDto;
@@ -17,15 +22,24 @@ import com.xy.mapper.*;
 import com.xy.utils.*;
 import com.xy.utils.consts.CommConsts;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.validation.constraints.NotBlank;
+import java.io.IOException;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.List;
 
 import static com.xy.utils.PlusBeans.*;
@@ -245,4 +259,89 @@ public class DeviceRegisterServiceImpl extends ServiceImpl<DeviceRegisterMapper,
         }
         return R.ok();
     }
+
+    @ApiOperation("上传sn注册设备")
+    @PostMapping("uploadSaveBySn")
+    public R uploadSaveBySn(@RequestParam("file") MultipartFile file, @RequestParam("deviceType") Integer deviceType, @RequestParam("devicePc") String devicePc, @RequestParam("assetNo") String assetNo) {
+        ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, 1)
+                .execute(() -> {
+                    try {
+                        EasyExcel.read(file.getInputStream(), UploadSaveBySn.class, new UploadSaveBySnListener(deviceCreateIdsService, this, deviceType, devicePc, assetNo)).sheet().doRead();
+                    } catch (IOException e) {
+                        log.error("", e);
+                    }
+                });
+        return R.ok();
+    }
+
+    @Slf4j
+    @RequiredArgsConstructor
+    public static class UploadSaveBySnListener implements ReadListener<UploadSaveBySn> {
+
+        private final DeviceCreateIdsServiceImpl deviceCreateIdsService;
+
+        private final DeviceRegisterServiceImpl deviceRegisterService;
+
+        private final Integer deviceType;
+
+        private final String devicePc;
+
+        private final String assetNo;
+
+        private List<UploadSaveBySn> sns = new ArrayList<>();
+
+        /**
+         * 这个每一条数据解析都会来调用
+         *
+         * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
+         * @param context
+         */
+        @Override
+        public void invoke(UploadSaveBySn data, AnalysisContext context) {
+            sns.add(data);
+        }
+
+        /**
+         * 所有数据解析完成了 都会来调用
+         *
+         * @param context
+         */
+        @Override
+        public void doAfterAllAnalysed(AnalysisContext context) {
+            log.info("上传sn注册设备文件解析完毕,总数量:{},批次:{}", sns.size(), devicePc);
+            //生成设备号
+            JList<DeviceCreateIds> deviceCreateIds = deviceCreateIdsService.save(new DeviceCreateIdsDto.Save()
+                    .setDeviceType(deviceType)
+                    .setDoorType("1")
+                    .setCreatePc(devicePc)
+                    .setNum(sns.size())
+            ).getData();
+            JList<Long> deviceIds = deviceCreateIds.getProperty(DeviceCreateIds::getDeviceId);
+            //注册设备
+            ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, sns.size());
+            for (int i = 0; i < sns.size(); i++) {
+                UploadSaveBySn sn = sns.get(i);
+                Long deviceId = deviceIds.get(i);
+                execute.execute(() -> {
+                    DeviceRegisterDto.Save save = new DeviceRegisterDto.Save()
+                            .setDeviceId(deviceId)
+                            .setDeviceSn(sn.getSn())
+                            .setDevicePc(devicePc)
+                            .setAssetNo(assetNo);
+                    R r = deviceRegisterService.save(save);
+                    if (r.getCode() == R.Enum.FAIL.getCode()) {
+                        log.error("{},{}", sn.getSn(), r.getMsg());
+                    }
+                });
+            }
+            execute.end();
+            log.info("上传sn注册设备注册完毕,批次:{}", devicePc);
+        }
+    }
+
+    @Data
+    public static class UploadSaveBySn {
+
+        private String sn;
+    }
 }

+ 2 - 1
device-api-service/src/main/java/com/xy/service/MqttServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.alipay.AliPay;
 import com.xy.annotate.Runners;
 import com.xy.annotate.Timer;
 import com.xy.collections.map.JHashMap;
@@ -123,9 +124,9 @@ public class MqttServiceImpl extends ServiceImpl<MqttCommandMapper, MqttCommand>
         snInit = true;
     }
 
-    @Timer
     @Override
     @ApiOperation("指令发送")
+    @AliPay(AliPay.Type.RESTART)
     public R<List<Tuple.Tuple3<Long, Long, Boolean>>> senCommand(List<CommandMqtt> commandMqtts) {
         //发送指令
         List<MqttDto> mqttDtos = new ArrayList<>();

+ 5 - 0
device-api-service/src/main/java/com/xy/utils/enums/DictEnum.java

@@ -30,6 +30,11 @@ public enum DictEnum {
     ENV("env", "环境标识"),
 
     ENV_PARAMS("env_params", "环境参数"),
+
+    DEVICE_CHARGING("device_charging", "设备计费标准"),
+
+    DEVICE_TYPE("device_type", "设备-机器类型"),
+
     ;
 
     private String key;

+ 10 - 0
device-api-service/src/main/java/com/xy/utils/enums/DictSonEnum.java

@@ -52,6 +52,16 @@ public enum DictSonEnum {
 
     ENV_PROD("prod", "环境标识-生产环境"),
 
+    DEVICE_CHARGING_X("x", "设备计费标准-机器激活后可使用天数"),
+
+    DEVICE_CHARGING_Y("y", "设备计费标准-机器欠费后可使用天数"),
+
+    DEVICE_CHARGING_100("100", "设备计费标准-余额续费方式"),
+
+    DEVICE_CHARGING_101("101", "设备计费标准-其他续费方式"),
+
+    DEVICE_TYPE_5("5", "设备-机器类型-支付宝视动态觉柜"),
+
     ;
 
     private String key;

+ 17 - 0
device-api-service/src/main/java/com/xy/utils/enums/SysCodeConfigureEnum.java

@@ -0,0 +1,17 @@
+package com.xy.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum SysCodeConfigureEnum {
+
+    /**
+     * 设备故障
+     */
+    D01("D01");
+
+    private String code;
+
+}

+ 59 - 0
device-api-service/src/main/resources/mapper/DeviceChargingMapper.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xy.mapper.DeviceChargingMapper">
+
+    <resultMap id="queryPageMap" type="com.xy.dto.DeviceChargingDto$PageVo">
+        <association property="deviceInfo" javaType="com.xy.dto.DeviceInfoDto$Vo">
+            <id column="device_id" property="deviceId"/>
+            <result column="device_name" property="deviceName"/>
+            <result column="lon" property="lon"/>
+            <result column="lat" property="lat"/>
+            <result column="device_type" property="deviceType"/>
+            <result column="merc_device_code" property="mercDeviceCode"/>
+            <result column="merc_id" property="mercId"/>
+            <result column="merc_code" property="mercCode"/>
+            <result column="place_id" property="placeId"/>
+            <result column="place_line_id" property="placeLineId"/>
+            <result column="district_id" property="districtId"/>
+            <result column="active_state" property="activeState"/>
+            <result column="active_time" property="activeTime"/>
+            <result column="busy_state" property="busyState"/>
+            <result column="show_status" property="showStatus"/>
+            <result column="freeze_status" property="freezeStatus"/>
+            <result column="device_img" property="deviceImg"/>
+            <result column="update_time" property="updateTime"/>
+            <result column="merc_name" property="mercName"/>
+            <result column="create_time" property="createTime"/>
+        </association>
+        <association property="deviceCharging" javaType="com.xy.dto.DeviceChargingDto$Vo">
+            <result column="charging_sum_money" property="chargingSumMoney" />
+            <result column="charging_x" property="chargingX" />
+            <result column="timeout" property="timeout" />
+            <result column="charging_create_time" property="createTime" />
+        </association>
+    </resultMap>
+
+    <select id="page" resultMap="queryPageMap">
+        select di.*,
+        dc.charging_sum_money, dc.charging_x, dc.timeout, dc.create_time as charging_create_time
+        from device_info di
+        join device_charging dc on(di.device_id = dc.device_id)
+        where
+        1 = 1
+        <if test="queryPage.mercId != null">
+            and di.merc_id = #{queryPage.mercId}
+        </if>
+        <if test="queryPage.deviceId != null">
+            and di.device_id = #{queryPage.deviceId}
+        </if>
+        <if test="queryPage.chargingStatus != null">
+            <if test="queryPage.chargingStatus == true">
+                and dc.timeout &lt;= #{queryPage.thisTime}
+            </if>
+            <if test="queryPage.chargingStatus == false">
+                and dc.timeout >= #{queryPage.thisTime}
+            </if>
+        </if>
+        order by dc.timeout asc
+    </select>
+</mapper>

+ 12 - 0
device-api-service/src/main/resources/mapper/DeviceDataMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xy.mapper.DeviceDataMapper">
+    <select id="dayChart" resultType="com.xy.dto.DeviceDataDto$DayChartVo">
+        SELECT date_value as time, sum(sales_count) num, sum(sales_money) total_money
+        FROM device_data
+        WHERE type = #{type}
+          and merc_id = #{mercId}
+          and date_value BETWEEN #{beginDateInt} and #{endDateInt}
+        GROUP BY date_value
+    </select>
+</mapper>

+ 1 - 1
device-api-service/src/main/resources/mapper/DeviceInfoMapper.xml

@@ -164,7 +164,7 @@
             and LOCATE(#{queryPage.deviceId}, info.device_id) > 0
         </if>
         <if test="queryPage.deviceIdList != null">
-            and device_id IN
+            and info.device_id IN
             <foreach collection="queryPage.deviceIdList" item="deviceId" open="(" close=")" separator=",">
                 #{deviceId}
             </foreach>

+ 95 - 0
device-api/src/main/java/com/xy/dto/DeviceChargingDto.java

@@ -0,0 +1,95 @@
+package com.xy.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.utils.PageBean;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotEmpty;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 设备计费表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public class DeviceChargingDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class Charging {
+
+        @NotEmpty(message = "设备id不能为空")
+        @ApiModelProperty(value = "设备id集合")
+        private List<Long> deviceIds;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page {
+
+        @ApiModelProperty("分页对象")
+        private PageBean page;
+
+        @ApiModelProperty("商户id")
+        private Long mercId;
+
+        @ApiModelProperty("设备id")
+        private Long deviceId;
+
+        @ApiModelProperty("缴费状态 true=已缴费 false=欠费")
+        private Boolean chargingStatus;
+
+        @ApiModelProperty(value = "当前系统时间", hidden = true)
+        private LocalDateTime thisTime = LocalDateTime.now();
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "累计续费金额")
+        private Integer chargingSumMoney;
+
+        @ApiModelProperty(value = "试用剩余天")
+        private Integer chargingX;
+
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageVo {
+
+        @ApiModelProperty(value = "计费信息")
+        private Vo deviceCharging;
+
+        @ApiModelProperty(value = "最新计费历史信息")
+        private DeviceChargingHistoryDto.Vo deviceChargingHistory;
+
+        @ApiModelProperty(value = "设备信息")
+        private DeviceInfoDto.Vo deviceInfo;
+
+        @ApiModelProperty(value = "计费标准金额/年")
+        private Integer chargingMoney;
+
+        @ApiModelProperty("缴费状态 true=已缴费 false=欠费")
+        private Boolean chargingStatus;
+    }
+
+}

+ 64 - 0
device-api/src/main/java/com/xy/dto/DeviceChargingHistoryDto.java

@@ -0,0 +1,64 @@
+package com.xy.dto;
+
+import com.xy.utils.PageBean;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 设备计费历史表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public class DeviceChargingHistoryDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "续费金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "续费方式")
+        private Integer chargingType;
+
+        @ApiModelProperty(value = "续费有效期")
+        private LocalDateTime chargingDateTime;
+
+        @ApiModelProperty(value = "创建时间")
+        private LocalDateTime createTime;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page {
+
+        @ApiModelProperty("分页对象")
+        private PageBean page;
+
+        @NotNull(message = "deviceId不能为空")
+        @ApiModelProperty("设备id")
+        private Long deviceId;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageVo extends Vo {
+
+        @ApiModelProperty(value = "设备信息")
+        private DeviceInfoDto.Vo deviceInfo;
+    }
+}

+ 94 - 10
device-api/src/main/java/com/xy/dto/DeviceDataDto.java

@@ -9,6 +9,7 @@ import lombok.Data;
 import lombok.experimental.Accessors;
 
 import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
@@ -25,7 +26,55 @@ public class DeviceDataDto {
 
     @Data
     @Accessors(chain = true)
-    public static class SumCountVo{
+    public static class DayChartDto {
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "统计类型(day,month,year)",required = true)
+        @NotNull(message = "统计类型不能为空")
+        private String type;
+
+        @NotNull(message = "开始时间不能为空")
+        @ApiModelProperty(value = "开始时间",required = true)
+        @JsonFormat(pattern = "yyyy-MM-dd")
+        private LocalDate beginDate;
+
+        @NotNull(message = "结束时间不能为空")
+        @JsonFormat(pattern = "yyyy-MM-dd")
+        @ApiModelProperty(value = "结束时间",required = true)
+        private LocalDate endDate;
+
+        public Integer getBeginInt() {
+            return Integer.valueOf(StrUtil.replace(beginDate.toString(), "-", ""));
+        }
+
+        public Integer getEndDateInt() {
+            return Integer.valueOf(StrUtil.replace(endDate.toString(), "-", ""));
+        }
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DayChartVo {
+        @ApiModelProperty("时间")
+        private Integer time;
+
+        @ApiModelProperty("笔数")
+        private Integer num;
+
+        @ApiModelProperty("销售额(分)")
+        private Integer totalMoney;
+
+        @ApiModelProperty("销售额(元)")
+        private BigDecimal totalMoneyYuan;
+
+        public BigDecimal getTotalMoneyYuan() {
+            return BigDecimal.valueOf(totalMoney).divide(new BigDecimal(100));
+        }
+    }
+    @Data
+    @Accessors(chain = true)
+    public static class SumCountVo {
         @ApiModelProperty(value = "营业额;单位分")
         private Integer salesMoney;
 
@@ -47,22 +96,23 @@ public class DeviceDataDto {
         @ApiModelProperty(value = "0元订单笔数")
         private Integer zeroCount;
     }
+
     @Data
     @Accessors(chain = true)
-    public static class SumCountDto{
-        @ApiModelProperty(value = "商户ID",required = true)
+    public static class SumCountDto {
+        @ApiModelProperty(value = "商户ID", required = true)
         private Long mercId;
 
         @NotNull(message = "统计类型不能为空")
-        @ApiModelProperty(value = "统计类型",required = true)
+        @ApiModelProperty(value = "统计类型", required = true)
         private String type;
 
         @NotNull(message = "排序字段不能为空")
-        @ApiModelProperty(value = "排序字段",required = true)
+        @ApiModelProperty(value = "排序字段", required = true)
         private String orderByKey;
 
         @NotNull(message = "排序方式不能为空")
-        @ApiModelProperty(value = "排序方式",required = true)
+        @ApiModelProperty(value = "排序方式", required = true)
         private String orderBy;
 
         @ApiModelProperty("开始时间")
@@ -72,18 +122,19 @@ public class DeviceDataDto {
         private String endDate;
 
         public String getBeginDate() {
-            return StrUtil.replace(beginDate,"-","");
+            return StrUtil.replace(beginDate, "-", "");
         }
+
         public String getEndDate() {
-            return StrUtil.replace(endDate,"-","");
+            return StrUtil.replace(endDate, "-", "");
         }
     }
 
     @Data
     @Accessors(chain = true)
-    public static class SumPageDto extends SumCountDto{
+    public static class SumPageDto extends SumCountDto {
         @NotNull(message = "分页信息不能为空")
-        @ApiModelProperty(value = "分页信息",required = true)
+        @ApiModelProperty(value = "分页信息", required = true)
         private PageBean page;
     }
 
@@ -117,6 +168,7 @@ public class DeviceDataDto {
         @ApiModelProperty(value = "0元订单笔数")
         private Integer zeroCount;
     }
+
     @Data
     @Accessors(chain = true)
     public static class Page extends Vo {
@@ -274,5 +326,37 @@ public class DeviceDataDto {
 
     }
 
+    @Data
+    @Accessors(chain = true)
+    public static class CountByDay {
+
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "日期")
+        private String dateValue;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class CountByMonth {
+
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "日期")
+        private String dateValue;
+
+
+    }
+
 
 }

+ 5 - 11
device-api/src/main/java/com/xy/dto/DeviceErrorsRecordDto.java

@@ -76,20 +76,14 @@ public class DeviceErrorsRecordDto {
         @ApiModelProperty(value = "设备编号")
         private Long deviceId;
 
+        @ApiModelProperty(value = "设备名称")
+        private String deviceName;
+
         @ApiModelProperty(value = "商户ID")
         private Long mercId;
 
-        @ApiModelProperty(value = "故障类型")
-        private Integer errorType;
-
-        @ApiModelProperty(value = "故障描述")
-        private String errorDescript;
-
-        @ApiModelProperty(value = "上位机版本号")
-        private String appUpmVersion;
-
-        @ApiModelProperty(value = "下位机版本号")
-        private String appDownmVersion;
+        @ApiModelProperty(value = "故障编码")
+        private String code;
 
         @ApiModelProperty(value = "创建时间")
         @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")

+ 43 - 2
device-api/src/main/java/com/xy/dto/DeviceInfoDto.java

@@ -238,6 +238,18 @@ public class DeviceInfoDto {
     @Accessors(chain = true)
     public static class Vo {
 
+        @ApiModelProperty("左门锁机状态名称")
+        private String deviceStateLName;
+
+        @ApiModelProperty("右门锁机状态名称")
+        private String deviceStateRName;
+
+        @ApiModelProperty("左门锁机状态,字典类型:devcie_lock_status")
+        private Integer deviceStateL;
+
+
+        @ApiModelProperty("右门锁机状态,字典类型:devcie_lock_status")
+        private Integer deviceStateR;
 
         @ApiModelProperty("设备id")
         private Long deviceId;
@@ -400,6 +412,21 @@ public class DeviceInfoDto {
         private Integer busyState;
 
 
+        @ApiModelProperty("左门锁机状态,字典类型:devcie_lock_status")
+        private Integer deviceStateL;
+
+
+        @ApiModelProperty("右门锁机状态,字典类型:devcie_lock_status")
+        private Integer deviceStateR;
+
+
+        @ApiModelProperty("左门锁机状态名称")
+        private String deviceStateLName;
+
+        @ApiModelProperty("右门锁机状态名称")
+        private String deviceStateRName;
+
+
         @DictFormat(DictConsts.DEVICE_FAULT_LEVEL)
         @ApiModelProperty("故障等级")
         private Integer faultLevel;
@@ -556,10 +583,10 @@ public class DeviceInfoDto {
         @ApiModelProperty(value = "离线设备数")
         private Integer offlineNum;
 
-        @ApiModelProperty(value = "运营设备数")
+        @ApiModelProperty(value = "锁机设备数")
         private Integer operatingNum;
 
-        @ApiModelProperty(value = "停业设备数")
+        @ApiModelProperty(value = "未锁机设备数")
         private Integer closedNum;
 
         @ApiModelProperty(value = "待补货设备数")
@@ -662,6 +689,20 @@ public class DeviceInfoDto {
         @ApiModelProperty("补货数")
         private Integer fillNum;
 
+
+        @ApiModelProperty("左门锁机状态名称")
+        private String deviceStateLName;
+
+        @ApiModelProperty("右门锁机状态名称")
+        private String deviceStateRName;
+
+        @ApiModelProperty("左门锁机状态,字典类型:devcie_lock_status")
+        private Integer deviceStateL;
+
+
+        @ApiModelProperty("右门锁机状态,字典类型:devcie_lock_status")
+        private Integer deviceStateR;
+
     }
 
 

+ 79 - 0
device-api/src/main/java/com/xy/dto/MercMiniDeviceDto.java

@@ -1,5 +1,7 @@
 package com.xy.dto;
 
+import cn.hutool.core.date.DateTime;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.experimental.Accessors;
@@ -71,6 +73,83 @@ public class MercMiniDeviceDto {
 
     }
 
+    @Data
+    @Accessors(chain = true)
+    public static class HomePageMonthDTO {
+
+        @ApiModelProperty(value = "日期", required = false)
+        @JsonFormat(pattern = "yyyy-MM")
+        private DateTime date;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class HomePageDayDTO {
+        @JsonFormat(pattern = "yyyy-MM-dd")
+        private DateTime date;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class HomePageMonthVO {
+        @ApiModelProperty(value = "本月收款")
+        private Integer monthReceivedMoney;
+        @ApiModelProperty(value = "本月销售-订单金额")
+        private Integer monthOrderTotalMoney;
+
+        @ApiModelProperty(value = "本月销售-到账金额")
+        private Integer monthOrderRealMoney;
+        @ApiModelProperty(value = "本月销售-数量")
+        private Integer monthOrderNum;
+
+        @ApiModelProperty(value = "本月订单-未收款金额")
+        private Integer noPaymentMoney;
+
+        @ApiModelProperty(value = "历史订单-未收款金额")
+        private Integer hisNoPaymentMoney;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class HomePageDayVO {
+        @ApiModelProperty(value = "今日收款")
+        private Integer todayReceivedMoney;
+        @ApiModelProperty(value = "今日补收-金额")
+        private Integer todayFillMoney;
+        @ApiModelProperty(value = "今日补收-数量")
+        private Integer todayFillOrderNum;
+
+        @ApiModelProperty(value = "今日补退-金额")
+        private Integer todayHisRefundMoney;
+
+        @ApiModelProperty(value = "今日补退-数量")
+        private Integer todayHisOrderRefundNum;
+
+        @ApiModelProperty(value = "今日退款-金额")
+        private Integer todayOrderRefundMoney;
+
+        @ApiModelProperty(value = "今日退款-数量")
+        private Integer todayOrderRefundNum;
+
+        @ApiModelProperty(value = "今日销售-订单金额")
+        private Integer todayOrderTotalMoney;
+
+        @ApiModelProperty(value = "今日销售-到账金额")
+        private Integer todayOrderRealMoney;
+        @ApiModelProperty(value = "今日销售-数量")
+        private Integer todayOrderNum;
+
+        @ApiModelProperty(value = "风险单-待处理数量")
+        private Integer toDoRiskOrderCount;
+
+        @ApiModelProperty(value = "风险单-今日处理数量")
+        private Integer toDayHandleRiskOrderCount;
+        @ApiModelProperty(value = "风险单-今日新增数量")
+        private Integer toDayNewRiskOrderCount;
+
+
+    }
+
     @Data
     @Accessors(chain = true)
     public static class DayCountVO {

+ 201 - 0
device-api/src/main/java/com/xy/dto/MercMiniSalseCountDto.java

@@ -0,0 +1,201 @@
+package com.xy.dto;
+
+import cn.hutool.core.date.DateTime;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+
+/**
+ * 商家端小程序销售统计-更多
+ */
+public class MercMiniSalseCountDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class UpdateInfo {
+        @NotNull(message = "deviceId不能为空")
+        @ApiModelProperty("设备id")
+        private Long deviceId;
+
+        @ApiModelProperty("设备名称")
+        private String deviceName;
+
+        @ApiModelProperty("点位id")
+        private Long placeId;
+
+        @ApiModelProperty("线路id")
+        private Long placeLineId;
+
+        @ApiModelProperty("区域id")
+        private Long districtId;
+
+        @ApiModelProperty("经度")
+        private String lon;
+
+        @ApiModelProperty("纬度")
+        private String lat;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Active {
+
+        @NotNull(message = "deviceId不能为空")
+        @ApiModelProperty("设备id")
+        private Long deviceId;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class BusySate {
+
+        @NotNull(message = "设备运营状态不能为空")
+        @ApiModelProperty("设备运营状态 1 运营中 2 已停运")
+        private Integer busyState;
+        @NotNull(message = "deviceId不能为空")
+        @ApiModelProperty("设备id")
+        private Long deviceId;
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class HomePageMonthDTO {
+        @ApiModelProperty(value = "日期", required = false)
+        @JsonFormat(pattern = "yyyy-MM")
+        private DateTime date;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DayDTO {
+
+        @ApiModelProperty(value = "日期", required = false)
+        @JsonFormat(pattern = "yyyy-MM-dd")
+        private DateTime date;
+
+        @ApiModelProperty(value = "商户ID", required = false)
+        private Long mercId;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DayDetailDTO {
+
+        @NotNull()
+        @ApiModelProperty(value = "日期", required = true)
+        @JsonFormat(pattern = "yyyy-MM-dd")
+        private DateTime date;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class HomePageMonthVO {
+        @ApiModelProperty(value = "本月收款")
+        private Integer monthReceivedMoney;
+        @ApiModelProperty(value = "本月销售-订单金额")
+        private Integer monthOrderTotalMoney;
+
+        @ApiModelProperty(value = "本月销售-到账金额")
+        private Integer monthOrderRealMoney;
+        @ApiModelProperty(value = "本月销售-数量")
+        private Integer monthOrderNum;
+
+        @ApiModelProperty(value = "本月订单-未收款金额")
+        private Integer noPaymentMoney;
+
+        @ApiModelProperty(value = "历史订单-未收款金额")
+        private Integer hisNoPaymentMoney;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class SalesCountDay {
+        @ApiModelProperty(value = "今日总收益=今日订单销售到账金额+今日补收合计")
+        private Integer dayTotalRevenue;
+
+        @ApiModelProperty(value = "今日订单销售-到账金额")
+        private Integer dayOrderRealMoney;
+
+        @ApiModelProperty(value = "今日订单销售-订单金额")
+        private Integer dayOrderTotalMoney;
+
+        @ApiModelProperty(value = "今日订单销售-订单数量")
+        private Integer dayOrderNum;
+
+        @ApiModelProperty(value = "今日订单销售-退款金额")
+        private Integer dayRefundMoney;
+
+        @ApiModelProperty(value = "今日订单销售-退款数量")
+        private Integer dayRefundNum;
+
+        @ApiModelProperty(value = "今日订单销售-挂账金额")
+        private Integer dayPayFailedMoney;
+
+
+        @ApiModelProperty(value = "今日订单销售-挂账数量")
+        private Integer dayPayFailedNum;
+
+        @ApiModelProperty(value = "今日订单销售-待确认订单数")
+        private Integer dayToBeConfirmedNum;
+
+        @ApiModelProperty(value = "今日订单销售-异常订单数量")
+        private Integer dayAbnormalOrderNum;
+
+
+        @ApiModelProperty(value = "历史订单今日补收-金额")
+        private Integer dayHisFillMoney;
+        @ApiModelProperty(value = "历史订单今日补收-订单数量")
+        private Integer dayHisFillNum;
+
+
+        @ApiModelProperty(value = "历史订单今日补退-订单金额")
+        private Integer dayHisRefundMoney;
+
+        @ApiModelProperty(value = "历史订单今日补退-订单数量")
+        private Integer dayHisRefundNum;
+
+
+        @ApiModelProperty(value = "风险单-待处理数量")
+        private Integer toDoRiskCount;
+
+        @ApiModelProperty(value = "风险单-今日处理数量")
+        private Integer dayRiskHandleCount;
+        @ApiModelProperty(value = "风险单-今日新增数量")
+        private Integer dayRiskAddCount;
+
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class MonthCountVO {
+        @ApiModelProperty(value = "本月总收益")
+        private Integer monthTotalRevenue;
+
+        @ApiModelProperty(value = "本月收益列表")
+        private List<DayRevenue> revenueList;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DayRevenue {
+        @ApiModelProperty(value = "日收益")
+        private Integer dayTotalRevenue;
+        @ApiModelProperty(value = "日期")
+        private String date;
+
+    }
+
+
+}

+ 16 - 0
device-api/src/main/java/com/xy/service/DeviceChargingHistoryService.java

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 设备计费历史表 服务类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@RestMappingController("/device-charging-history")
+public interface DeviceChargingHistoryService {
+
+}

+ 16 - 0
device-api/src/main/java/com/xy/service/DeviceChargingService.java

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 设备计费表 服务类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@RestMappingController("/device-charging")
+public interface DeviceChargingService {
+
+}

+ 27 - 0
device-api/src/main/java/com/xy/service/DeviceDataService.java

@@ -1,6 +1,13 @@
 package com.xy.service;
 
 import com.xy.annotate.RestMappingController;
+import com.xy.dto.DeviceDataDto;
+import com.xy.utils.R;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
 
 /**
  * <p>
@@ -12,6 +19,26 @@ import com.xy.annotate.RestMappingController;
  */
 @RestMappingController("/device-data")
 public interface DeviceDataService {
+    /**
+     * 指定查询商户所有设备某天数据
+     *
+     * @param dto
+     * @return
+     */
+    @PostMapping("getByDay")
+    R<List<DeviceDataDto.Vo>> getMercDataOneDay(@RequestBody @Validated DeviceDataDto.CountByDay dto);
+
+    /**
+     * 指定查询商户所有设备某月数据
+     *
+     * @param dto
+     * @return
+     */
+    @PostMapping("getMercDataOneMonth")
+    R<List<DeviceDataDto.Vo>> getMercDataOneMonth(@RequestBody @Validated DeviceDataDto.CountByMonth dto);
+
 
+    @PostMapping("dayChart")
+    R<List<DeviceDataDto.DayChartVo>> dayChart(@RequestBody DeviceDataDto.DayChartDto dto);
 
 }

+ 14 - 8
device-api/src/main/java/com/xy/utils/enums/DeviceErrorRecordTypesEnum.java

@@ -4,7 +4,7 @@ import lombok.Getter;
 
 /**
  * <p>
- * 设备故障类型枚举
+ * 设备故障编码枚举
  * </p>
  *
  * @author hechunping
@@ -13,16 +13,22 @@ import lombok.Getter;
 @Getter
 public enum DeviceErrorRecordTypesEnum {
 
-    NET("1","联网故障"),
-    DOOR_LOCK("2","门锁故障"),
-    T("3","温控仪故障"),
-    LIGHT("4","灯光故障"),
-    CAMERA("4","摄像头故障"),
-    COMPRESSOR("4","压缩机故障"),
+    NET("D001", "联网故障"),
+
+    DOOR_LOCK("D002", "门锁故障"),
+
+    T("D003", "温控仪故障"),
+
+    LIGHT("D004", "灯光故障"),
+
+    CAMERA("D005", "摄像头故障"),
+
+    COMPRESSOR("D006", "压缩机故障"),
     ;
     private String code;
     private String msg;
-    DeviceErrorRecordTypesEnum(String code,String msg){
+
+    DeviceErrorRecordTypesEnum(String code, String msg) {
         this.code = code;
         this.msg = msg;
     }

+ 0 - 28
device-api/src/main/java/com/xy/utils/enums/DeviceErrorTypesEnum.java

@@ -1,28 +0,0 @@
-package com.xy.utils.enums;
-
-import lombok.Getter;
-
-@Getter
-public enum DeviceErrorTypesEnum {
-    DEVICE_ERROR_TYPES_1(1, "联网故障"),
-
-    DEVICE_ERROR_TYPES_2(2, "门锁故障"),
-
-    DEVICE_ERROR_TYPES_3(3, "温控仪故障"),
-
-    DEVICE_ERROR_TYPES_4(4, "灯光故障"),
-
-    DEVICE_ERROR_TYPES_5(5, "摄像头故障"),
-
-    DEVICE_ERROR_TYPES_6(6, "压缩机故障"),
-    ;
-
-    private int key;
-
-    private String msg;
-
-    DeviceErrorTypesEnum(int key, String msg) {
-        this.key = key;
-        this.msg = msg;
-    }
-}

+ 48 - 0
device-api/src/main/java/com/xy/utils/enums/DeviceLockState.java

@@ -0,0 +1,48 @@
+package com.xy.utils.enums;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.ToString;
+
+/**
+ * 锁机状态 1 未锁机 2 已锁机
+ *
+ * @author 谭斌
+ */
+@Getter
+@ToString
+@AllArgsConstructor
+public enum DeviceLockState {
+
+
+    UN_LOCK(1, "未锁机"),
+    LOCK(2, "已锁机");
+
+    /**
+     * 编码值
+     */
+    private Integer code;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+
+    /**
+     * 通过code获取enum
+     *
+     * @param code
+     * @return
+     */
+    public static DeviceLockState getEnumByCode(Integer code) {
+        DeviceLockState[] values = values();
+        for (DeviceLockState value : values) {
+            if (value.getCode().equals(code)) {
+                return value;
+            }
+        }
+        return null;
+    }
+}

+ 5 - 2
device-start/pom.xml

@@ -29,7 +29,6 @@
             <artifactId>device-api-service-merc-mini</artifactId>
             <version>1.0</version>
         </dependency>
-
         <dependency>
             <groupId>com.xy</groupId>
             <artifactId>device-api-service-member</artifactId>
@@ -56,12 +55,16 @@
             <artifactId>merc-api-cloud</artifactId>
             <version>1.0</version>
         </dependency>
-
         <dependency>
             <groupId>com.xy</groupId>
             <artifactId>sys-api-feign</artifactId>
             <version>1.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>merc-api-cloud</artifactId>
+            <version>1.0</version>
+        </dependency>
 
         <dependency>
             <groupId>com.xy</groupId>