李进 2 år sedan
förälder
incheckning
f313933ded
28 ändrade filer med 898 tillägg och 3 borttagningar
  1. 10 0
      device-api-cloud/src/main/java/com/xy/feign/JobFeign.java
  2. 10 0
      device-api-cloud/src/main/java/com/xy/feign/MqttFeign.java
  3. 27 0
      device-api-cloud/src/main/java/com/xy/service/MqttServiceImpl.java
  4. 19 0
      device-api-cloud/src/main/java/com/xy/service/job/JobServiceImpl.java
  5. 15 0
      device-api-service/pom.xml
  6. 85 0
      device-api-service/src/main/java/com/xy/entity/MqttCommand.java
  7. 75 0
      device-api-service/src/main/java/com/xy/job/MqttCommandJob.java
  8. 9 0
      device-api-service/src/main/java/com/xy/mapper/MqttCommandMapper.java
  9. 107 0
      device-api-service/src/main/java/com/xy/service/MqttServiceImpl.java
  10. 30 0
      device-api/src/main/java/com/xy/dto/BackMqttDto.java
  11. 43 0
      device-api/src/main/java/com/xy/dto/MqttDto.java
  12. 32 0
      device-api/src/main/java/com/xy/dto/job/JobDto.java
  13. 34 0
      device-api/src/main/java/com/xy/dto/pater/PaterDto.java
  14. 58 0
      device-api/src/main/java/com/xy/dto/son/CameraDto.java
  15. 16 0
      device-api/src/main/java/com/xy/dto/son/CellDto.java
  16. 16 0
      device-api/src/main/java/com/xy/dto/son/CheckDto.java
  17. 25 0
      device-api/src/main/java/com/xy/dto/son/LampDto.java
  18. 16 0
      device-api/src/main/java/com/xy/dto/son/LockDeviceDto.java
  19. 23 0
      device-api/src/main/java/com/xy/dto/son/LockDto.java
  20. 22 0
      device-api/src/main/java/com/xy/dto/son/LogDto.java
  21. 21 0
      device-api/src/main/java/com/xy/dto/son/TemperatureDto.java
  22. 36 0
      device-api/src/main/java/com/xy/service/MqttService.java
  23. 25 0
      device-api/src/main/java/com/xy/service/job/JobService.java
  24. 93 0
      device-api/src/main/java/com/xy/utils/CommandUtils.java
  25. 33 0
      device-api/src/main/java/com/xy/utils/enums/MqttEnum.java
  26. 2 0
      device-start/src/main/java/com/xy/StartCloud.java
  27. 12 1
      device-start/src/main/resources/bootstrap-uat.yml
  28. 4 2
      device-start/src/main/resources/bootstrap.yml

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

@@ -0,0 +1,10 @@
+package com.xy.feign;
+
+import com.xy.FeignInterceptor;
+import com.xy.service.job.JobService;
+import com.xy.utils.CommonConst;
+import org.springframework.cloud.openfeign.FeignClient;
+
+@FeignClient(value = CommonConst.MQTT_NAME, configuration = FeignInterceptor.class)
+public interface JobFeign extends JobService {
+}

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

@@ -0,0 +1,10 @@
+package com.xy.feign;
+
+import com.xy.FeignInterceptor;
+import com.xy.service.MqttService;
+import com.xy.utils.CommonConst;
+import org.springframework.cloud.openfeign.FeignClient;
+
+@FeignClient(value = CommonConst.MQTT_NAME, configuration = FeignInterceptor.class)
+public interface MqttFeign extends MqttService {
+}

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

@@ -0,0 +1,27 @@
+package com.xy.service;
+
+import com.xy.dto.BackMqttDto;
+import com.xy.dto.MqttDto;
+import com.xy.feign.MqttFeign;
+import com.xy.utils.R;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class MqttServiceImpl implements MqttFeign {
+
+    private MqttFeign mqttFeign;
+
+    @Override
+    public List<MqttDto.Vo> sendMqtt(List<MqttDto> mqttDtos) {
+        return mqttFeign.sendMqtt(mqttDtos);
+    }
+
+    @Override
+    public R mqttBack(BackMqttDto backMqttDto) {
+        return mqttFeign.mqttBack(backMqttDto);
+    }
+}

+ 19 - 0
device-api-cloud/src/main/java/com/xy/service/job/JobServiceImpl.java

@@ -0,0 +1,19 @@
+package com.xy.service.job;
+
+import com.xy.dto.job.JobDto;
+import com.xy.feign.JobFeign;
+import com.xy.utils.R;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class JobServiceImpl implements JobFeign {
+
+    private JobFeign jobFeign;
+
+    @Override
+    public R<Long> saveJob(JobDto demoJobDto) {
+        return jobFeign.saveJob(demoJobDto);
+    }
+}

+ 15 - 0
device-api-service/pom.xml

@@ -45,5 +45,20 @@
             <artifactId>xy-server-web</artifactId>
             <version>1.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>xy-mqtt</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>xy-es</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>xy-job</artifactId>
+            <version>1.0</version>
+        </dependency>
     </dependencies>
 </project>

+ 85 - 0
device-api-service/src/main/java/com/xy/entity/MqttCommand.java

@@ -0,0 +1,85 @@
+package com.xy.entity;
+
+import cn.easyes.annotation.IndexId;
+import cn.easyes.annotation.IndexName;
+import cn.easyes.annotation.rely.IdType;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * mqtt指令索引
+ */
+@Data
+@Accessors(chain = true)
+@IndexName("mqtt_command")
+public class MqttCommand {
+
+    @IndexId(type = IdType.CUSTOMIZE)
+    private String id;
+
+    /**
+     * 是否调试
+     */
+    private Boolean debug;
+
+    /**
+     * 指令类型
+     */
+    private String type;
+
+    /**
+     * 指令状态 1=已发送 2=发送失败 3=已执行 4=执行失败,5=执行超时 6=已完成
+     */
+    private Integer status;
+
+    /**
+     * 指令完整值
+     */
+    private String value;
+
+    /**
+     * 指令发送时间
+     */
+    private String sendTime;
+
+    /**
+     * 指令执行时间
+     */
+    private String execTime;
+
+    /**
+     * 指令过期时间
+     */
+    private String timeout;
+
+    /**
+     * 接收指令的topic
+     */
+    private String topic;
+
+    /**
+     * 是否应答
+     */
+    private Boolean ack;
+
+    /**
+     * 消息级别
+     */
+    private Integer level;
+
+    /**
+     * 已发送次数
+     */
+    private Integer num;
+
+    /**
+     * 消息消费时间(延迟消费)
+     */
+    private String delayTime;
+
+    /**
+     * 错误日志
+     */
+    private String error;
+
+}

+ 75 - 0
device-api-service/src/main/java/com/xy/job/MqttCommandJob.java

@@ -0,0 +1,75 @@
+package com.xy.job;
+
+import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+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.entity.MqttCommand;
+import com.xy.mapper.MqttCommandMapper;
+import com.xy.utils.DataTime;
+import com.xy.utils.JobUtils;
+import com.xy.utils.enums.MqttEnum;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 指令定时器
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class MqttCommandJob {
+
+    private MqttCommandMapper mqttCommandMapper;
+
+    /**
+     * 指令数据清除
+     *
+     * @return
+     */
+    @XxlJob("commandClean")
+    public ReturnT<String> commandClean() {
+        //指令保留的天数
+        Integer saveDay = JobUtils.getPrams().gtInt();
+        saveDay = saveDay == null ? 30 : saveDay;
+        LambdaEsQueryWrapper<MqttCommand> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<MqttCommand>()
+                .le(MqttCommand::getSendTime, DataTime.getStringAround(0, 0, (~(saveDay - 1)), 0, 0, 0));
+        Integer count = mqttCommandMapper.delete(lambdaEsQueryWrapper);
+        log.info("已清除指令数据:{}条", count);
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 指令数据闭环
+     *
+     * @return
+     */
+    @XxlJob("commandDataCloud")
+    public ReturnT<String> commandDataCloud() {
+        //过期时间小于当前时间的阈值,单位s
+        Integer threshold = JobUtils.getPrams().gtInt();
+        threshold = threshold == null ? 0 : threshold;
+        LambdaEsQueryWrapper<MqttCommand> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<MqttCommand>()
+                .in(MqttCommand::getStatus, Arrays.asList(MqttEnum.COMMAND_SEND.getKey(), MqttEnum.COMMAND_SEND_FAIL.getKey()))
+                .le(MqttCommand::getTimeout, DataTime.getStringAround(0, 0, 0, 0, 0, (~(threshold - 1))));
+        List<MqttCommand> mqttCommands = mqttCommandMapper.selectList(lambdaEsQueryWrapper);
+        if (mqttCommands.size() == 0) {
+            return ReturnT.SUCCESS;
+        }
+        JList<MqttCommand> list = new JArrayList<>(mqttCommands);
+        //发送但没有回执的数据
+        JList<MqttCommand> sends = list.filter().eq(MqttCommand::getStatus, MqttEnum.COMMAND_SEND.getKey()).list();
+        sends.forEach(mqttCommand -> mqttCommand.setStatus(Integer.parseInt(MqttEnum.COMMAND_EXC_TIMEOUT.getKey())));
+        mqttCommandMapper.updateBatchByIds(sends);
+        log.info("已处理发送但没有回执的指令数据:{}条", sends.size());
+        //发送失败的数据
+        JList<MqttCommand> sendFails = list.filter().eq(MqttCommand::getStatus, MqttEnum.COMMAND_SEND_FAIL.getKey()).list();
+        //todo 计数报表
+        return ReturnT.SUCCESS;
+    }
+}

+ 9 - 0
device-api-service/src/main/java/com/xy/mapper/MqttCommandMapper.java

@@ -0,0 +1,9 @@
+package com.xy.mapper;
+
+import cn.easyes.core.conditions.interfaces.BaseEsMapper;
+import com.xy.entity.MqttCommand;
+
+public interface MqttCommandMapper extends BaseEsMapper<MqttCommand> {
+    
+
+}

+ 107 - 0
device-api-service/src/main/java/com/xy/service/MqttServiceImpl.java

@@ -0,0 +1,107 @@
+package com.xy.service;
+
+import cn.hutool.json.JSONObject;
+import com.github.yitter.idgen.YitIdHelper;
+import com.xy.dto.BackMqttDto;
+import com.xy.dto.MqttDto;
+import com.xy.dto.pater.PaterDto;
+import com.xy.entity.MqttCommand;
+import com.xy.mapper.MqttCommandMapper;
+import com.xy.producer.MqttProducer;
+import com.xy.utils.*;
+import com.xy.utils.enums.MqttEnum;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@Api(tags = "mqtt接口")
+@AllArgsConstructor
+public class MqttServiceImpl implements MqttService {
+
+    private MqttProducer mqttProducer;
+
+    private MqttCommandMapper mqttCommandMapper;
+
+    @Override
+    @ApiOperation("指令发布")
+    public List<MqttDto.Vo> sendMqtt(List<MqttDto> mqttDtos) {
+        List<MqttDto.Vo> list = new ArrayList<>(mqttDtos.size());
+        mqttDtos.forEach(mqttDto -> {
+            //给予默认值
+            JSONObject command = mqttDto.getCommand();
+            command.set(LambdaUtils.getProperty(PaterDto::getSn), YitIdHelper.nextId())
+                    .set(LambdaUtils.getProperty(PaterDto::getTime), DataTime.getSring());
+            //延迟发布处理
+            String delayTime = mqttDto.getDelayTime();
+            String topic = mqttDto.getTopic();
+            if (!StringUtils.isEmpty(delayTime)) {
+                //消息消费时间 - 发布时间的差值 = 距今被消费的秒数
+                long m = DataTime.diff(DataTime.toLocal(command.getStr(LambdaUtils.getProperty(PaterDto::getTime))), DataTime.toLocal(delayTime), "s");
+                topic = String.format("$delayed/%d/%s", m, mqttDto.getTopic());
+                mqttDto.setTimeout(mqttDto.getTimeout() + (int) m);
+            }
+            //处理消息过期时间
+            command.set(LambdaUtils.getProperty(PaterDto::getTimeout), DataTime.getStringAround(0, 0, 0, 0, 0, mqttDto.getTimeout()));
+            //写入新的指令json
+            mqttDto.setCommand(command);
+            String workSn = command.getStr(LambdaUtils.getProperty(PaterDto::getWorkSn));
+            try {
+                //发送消息
+                mqttProducer.sendToMqtt(command.toString(), topic, mqttDto.getLevel());
+                //指令记录
+                saveMqttCommand(mqttDto, command.getBool(LambdaUtils.getProperty(PaterDto::getAck)) ? MqttEnum.COMMAND_SEND.getKey() : MqttEnum.COMMAND_SUCCESS.getKey(), null);
+                list.add(new MqttDto.Vo().setWorkSn(workSn).setResult(true));
+            } catch (Exception e) {
+                //指令记录
+                saveMqttCommand(mqttDto, MqttEnum.COMMAND_SEND_FAIL.getKey(), e.getMessage());
+                list.add(new MqttDto.Vo().setWorkSn(workSn).setResult(false));
+            }
+        });
+        return list;
+    }
+
+    @Override
+    @ApiOperation("指令结果回执")
+    public R mqttBack(BackMqttDto backMqttDto) {
+        MqttCommand mqttCommand = mqttCommandMapper.selectById(backMqttDto.getSn());
+        if (!Emptys.check(mqttCommand)) {
+            return R.fail("数据不存在");
+        }
+        //重复上报,前面的时间不能覆盖后面的时间
+        if (!StringUtils.isEmpty(mqttCommand.getExecTime())) {
+            if (DataTime.stringContrast(DataTime.toString(backMqttDto.getExecTime()), mqttCommand.getExecTime()) < 0) {
+                return R.ok();
+            }
+        }
+        mqttCommand.setStatus(Integer.parseInt(backMqttDto.getBool() ? MqttEnum.COMMAND_SUCCESS.getKey() : MqttEnum.COMMAND_EXC_FAIL.getKey()))
+                .setExecTime(DataTime.toString(backMqttDto.getExecTime()));
+        mqttCommandMapper.updateById(mqttCommand);
+        return R.ok();
+    }
+
+    /**
+     * 新增指令记录
+     *
+     * @param mqttDto 参数对象
+     * @param status  状态
+     * @param error   错误信息
+     */
+    private void saveMqttCommand(MqttDto mqttDto, String status, String error) {
+        PaterDto command = mqttDto.getCommand().toBean(PaterDto.class);
+        MqttCommand mqttCommand = Beans.copy(Beans.copy(MqttCommand.class, mqttDto), command)
+                .setId(command.getSn())
+                .setStatus(Integer.parseInt(status))
+                .setValue(mqttDto.getCommand().toString())
+                .setSendTime(command.getTime())
+                .setExecTime(status.equals(MqttEnum.COMMAND_SUCCESS.getKey()) ? DataTime.getSring() : null)
+                .setNum(1)
+                .setError(error);
+        mqttCommandMapper.insert(mqttCommand);
+    }
+}

+ 30 - 0
device-api/src/main/java/com/xy/dto/BackMqttDto.java

@@ -0,0 +1,30 @@
+package com.xy.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+@Data
+@ApiModel("指令执行结果回执交互类")
+@Accessors(chain = true)
+public class BackMqttDto {
+
+    @NotBlank(message = "sn不能为空")
+    @ApiModelProperty(value = "sn编号", required = true)
+    private String sn;
+
+    @NotNull(message = "bool不能为空")
+    @ApiModelProperty(value = "结果 true=成功 false=失败", required = true)
+    private Boolean bool;
+
+    @NotNull(message = "execTime不能为空")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "执行时间 yyyy-MM-dd HH:mm:ss", required = true)
+    private LocalDateTime execTime;
+}

+ 43 - 0
device-api/src/main/java/com/xy/dto/MqttDto.java

@@ -0,0 +1,43 @@
+package com.xy.dto;
+
+import cn.hutool.json.JSONObject;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("指令交互类")
+@Accessors(chain = true)
+public class MqttDto {
+
+    @ApiModelProperty(value = "设备topic", required = true)
+    private String topic;
+
+    @ApiModelProperty("是否调试模式 默认=false")
+    private Boolean debug = false;
+
+    @ApiModelProperty("消息级别qs 默认=1")
+    private Integer level = 1;
+
+    @ApiModelProperty("消息消费时间(延迟消费) yyyy-MM-dd HH:mm:ss")
+    private String delayTime;
+
+    @ApiModelProperty("指令有效期,单位:s 默认=60")
+    private Integer timeout = 60;
+
+    @ApiModelProperty(value = "指令json", required = true)
+    private JSONObject command;
+
+    @Data
+    @ApiModel("指令返参类")
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty("业务系统sn编号")
+        private String workSn;
+
+        @ApiModelProperty("结果值")
+        private Boolean result;
+    }
+}

+ 32 - 0
device-api/src/main/java/com/xy/dto/job/JobDto.java

@@ -0,0 +1,32 @@
+package com.xy.dto.job;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("任务")
+@Accessors(chain = true)
+public class JobDto {
+
+
+    @ApiModelProperty(value = "任务开始时间", required = true)
+    private String StartTime;
+
+    @ApiModelProperty(value = "任务参数")
+    private String params;
+
+    @ApiModelProperty(value = "回调得类全类名")
+    private String processorInfo;
+
+    @ApiModelProperty(value = "任务ID 为空则新增任务")
+    private String jobId;
+
+    @ApiModelProperty(value = "任务名称")
+    private String jobName;
+
+    @ApiModelProperty(value = "任务描述")
+    private String jobDescription;
+    
+}

+ 34 - 0
device-api/src/main/java/com/xy/dto/pater/PaterDto.java

@@ -0,0 +1,34 @@
+package com.xy.dto.pater;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("指令通用父类")
+@Accessors(chain = true)
+public class PaterDto {
+
+    @ApiModelProperty(value = "sn编号", hidden = true)
+    private String sn;
+
+    @ApiModelProperty(value = "业务系统sn编号")
+    private String workSn;
+
+    @ApiModelProperty("业务类型(大类) issue=服务器下发设备执行指令 report=服务器通知设备上报信息")
+    private Integer work;
+
+    @ApiModelProperty(value = "指令类型(小类) 对应枚举类MqttEnum")
+    private String type;
+
+    @ApiModelProperty("是否应答 默认=true")
+    private Boolean ack = true;
+
+    @ApiModelProperty(value = "指令发送时间", hidden = true)
+    private String time;
+
+    @ApiModelProperty(value = "指令过期时间", hidden = true)
+    private String timeout;
+
+}

+ 58 - 0
device-api/src/main/java/com/xy/dto/son/CameraDto.java

@@ -0,0 +1,58 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@ApiModel("摄像头")
+@Accessors(chain = true)
+public class CameraDto extends PaterDto {
+
+    @ApiModelProperty("摄像头编号")
+    private String cameraId;
+
+    @ApiModelProperty("视频帧率")
+    private BigDecimal videoRate;
+
+    @ApiModelProperty("视频码流")
+    private BigDecimal videoStream;
+
+    @ApiModelProperty("清空视频")
+    private Boolean clearVideo;
+
+    @ApiModelProperty("清空图片")
+    private Boolean clearTake;
+
+    @ApiModelProperty("清理指定日期视频")
+    private String clearVideoByTime;
+
+    @ApiModelProperty("清理指定日期图片")
+    private String clearTakeByTime;
+
+    @ApiModelProperty("录制指定时长的视频 单位:秒")
+    private Integer videoByTime;
+
+    @ApiModelProperty("拍摄指定次数的照片 单位:次")
+    private Integer takeByNum;
+
+    @ApiModelProperty("开关 true=开 false=关")
+    private Boolean onff;
+
+    @ApiModelProperty("补报视频/图片")
+    private List<Repeat> repeat;
+
+    @Data
+    public static class Repeat {
+        @ApiModelProperty("订单编号")
+        private String orderId;
+
+        @ApiModelProperty("业务类型")
+        private String type;
+    }
+}

+ 16 - 0
device-api/src/main/java/com/xy/dto/son/CellDto.java

@@ -0,0 +1,16 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("电池")
+@Accessors(chain = true)
+public class CellDto extends PaterDto {
+
+    @ApiModelProperty("开关 true=开 false=关")
+    private Boolean onff;
+}

+ 16 - 0
device-api/src/main/java/com/xy/dto/son/CheckDto.java

@@ -0,0 +1,16 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("自检")
+@Accessors(chain = true)
+public class CheckDto extends PaterDto {
+
+    @ApiModelProperty("自检指令")
+    private Boolean check;
+}

+ 25 - 0
device-api/src/main/java/com/xy/dto/son/LampDto.java

@@ -0,0 +1,25 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+@Data
+@ApiModel("灯")
+@Accessors(chain = true)
+public class LampDto extends PaterDto {
+
+    @ApiModelProperty("灯编号")
+    private String lampId;
+
+    @ApiModelProperty("灯光值")
+    private BigDecimal value;
+
+    @ApiModelProperty("开关 true=开 false=关")
+    private Boolean onff;
+
+}

+ 16 - 0
device-api/src/main/java/com/xy/dto/son/LockDeviceDto.java

@@ -0,0 +1,16 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("锁机")
+@Accessors(chain = true)
+public class LockDeviceDto extends PaterDto {
+
+    @ApiModelProperty("锁机指令")
+    private Boolean lockDevice;
+}

+ 23 - 0
device-api/src/main/java/com/xy/dto/son/LockDto.java

@@ -0,0 +1,23 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("门锁")
+@Accessors(chain = true)
+public class LockDto extends PaterDto {
+
+    @ApiModelProperty("门锁编号")
+    private String lockId;
+
+    @ApiModelProperty("开关 true=开 false=关")
+    private Boolean onff;
+
+    @ApiModelProperty("订单号 开锁时需要")
+    private String orderNo;
+
+}

+ 22 - 0
device-api/src/main/java/com/xy/dto/son/LogDto.java

@@ -0,0 +1,22 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@ApiModel("日志")
+@Accessors(chain = true)
+public class LogDto extends PaterDto {
+
+    @ApiModelProperty("清空日志")
+    private Boolean clear;
+
+    @ApiModelProperty("开始截取的时间")
+    private Integer begin;
+
+    @ApiModelProperty("结束截取的时间")
+    private Integer end;
+}

+ 21 - 0
device-api/src/main/java/com/xy/dto/son/TemperatureDto.java

@@ -0,0 +1,21 @@
+package com.xy.dto.son;
+
+import com.xy.dto.pater.PaterDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+@Data
+@ApiModel("温度")
+@Accessors(chain = true)
+public class TemperatureDto extends PaterDto {
+
+    @ApiModelProperty("温度值")
+    private BigDecimal value;
+
+    @ApiModelProperty("开关 true=开 false=关")
+    private Boolean onff;
+}

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

@@ -0,0 +1,36 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.BackMqttDto;
+import com.xy.dto.MqttDto;
+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;
+
+/**
+ * mqtt接口
+ */
+@RestMappingController("mqtt")
+public interface MqttService {
+
+    /**
+     * 指令发布
+     *
+     * @param mqttDtos
+     * @return k=topic v=布尔结果
+     */
+    @PostMapping("sendMqtt")
+    List<MqttDto.Vo> sendMqtt(@RequestBody List<MqttDto> mqttDtos);
+
+    /**
+     * 指令结果回执
+     *
+     * @param backMqttDto
+     * @return
+     */
+    @PostMapping("mqttBack")
+    R mqttBack(@Validated @RequestBody BackMqttDto backMqttDto);
+}

+ 25 - 0
device-api/src/main/java/com/xy/service/job/JobService.java

@@ -0,0 +1,25 @@
+package com.xy.service.job;
+
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.job.JobDto;
+import com.xy.utils.R;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * 定时任务操作接口
+ */
+@RestMappingController("job")
+public interface JobService {
+
+
+    /**
+     * 保存任务
+     *
+     * @param demoJobDto
+     * @return 任务ID
+     */
+    @PostMapping("saveJob")
+    R<Long> saveJob(@RequestBody JobDto demoJobDto);
+
+}

+ 93 - 0
device-api/src/main/java/com/xy/utils/CommandUtils.java

@@ -0,0 +1,93 @@
+package com.xy.utils;
+
+import com.xy.dto.son.*;
+import com.xy.utils.enums.MqttEnum;
+import lombok.SneakyThrows;
+
+import java.lang.reflect.Method;
+
+/**
+ * 指令构造工具类
+ */
+public class CommandUtils {
+
+    @SneakyThrows
+    private static <T> T news(Class<T> tClass, String type) {
+        T t = tClass.newInstance();
+        Method setType = tClass.getMethod("setType", String.class);
+        setType.invoke(t, type);
+        return t;
+    }
+
+    /**
+     * 摄像头
+     *
+     * @return
+     */
+    public static CameraDto camera() {
+        return news(CameraDto.class, MqttEnum.COMMAND_CAMERAS.getKey());
+    }
+
+    /**
+     * 电池
+     *
+     * @return
+     */
+    public static CellDto cell() {
+        return news(CellDto.class, MqttEnum.COMMAND_CELL.getKey());
+    }
+
+    /**
+     * 自检
+     *
+     * @return
+     */
+    public static CheckDto check() {
+        return news(CheckDto.class, MqttEnum.COMMAND_CHECK.getKey());
+    }
+
+    /**
+     * 灯
+     *
+     * @return
+     */
+    public static LampDto lamp() {
+        return news(LampDto.class, MqttEnum.COMMAND_LAMP.getKey());
+    }
+
+    /**
+     * 锁机
+     *
+     * @return
+     */
+    public static LockDeviceDto LockDevice() {
+        return news(LockDeviceDto.class, MqttEnum.COMMAND_LOCK_DEVICE.getKey());
+    }
+
+    /**
+     * 门锁
+     *
+     * @return
+     */
+    public static LockDto lock() {
+        return news(LockDto.class, MqttEnum.COMMAND_LOCK.getKey());
+    }
+
+    /**
+     * 日志
+     *
+     * @return
+     */
+    public static LogDto log() {
+        return news(LogDto.class, MqttEnum.COMMAND_LOG.getKey());
+    }
+
+    /**
+     * 温度
+     *
+     * @return
+     */
+    public static TemperatureDto temperature() {
+        return news(TemperatureDto.class, MqttEnum.COMMAND_TEMPERATURE.getKey());
+    }
+}

+ 33 - 0
device-api/src/main/java/com/xy/utils/enums/MqttEnum.java

@@ -0,0 +1,33 @@
+package com.xy.utils.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum MqttEnum {
+    //指令类型
+    COMMAND_CHECK("check", "自检指令"),
+    COMMAND_LOCK_DEVICE("lockDevice", "锁机指令"),
+    COMMAND_LOCK("lock", "门锁指令"),
+    COMMAND_TEMPERATURE("temperature", "温度指令"),
+    COMMAND_LAMP("lamp", "灯光指令"),
+    COMMAND_CAMERAS("camera", "摄像头指令"),
+    COMMAND_CELL("cell", "电池指令"),
+    COMMAND_LOG("log", "日志指令"),
+    //指令状态
+    COMMAND_SEND("1", "已发送"),
+    COMMAND_SEND_FAIL("2", "发送失败"),
+    COMMAND_EXECUTE("3", "已执行"),
+    COMMAND_EXC_FAIL("4", "执行失败"),
+    COMMAND_EXC_TIMEOUT("5", "执行超时"),
+    COMMAND_SUCCESS("6", "已完成"),
+    ;
+
+    private String key;
+
+    private String msg;
+
+    MqttEnum(String key, String msg) {
+        this.key = key;
+        this.msg = msg;
+    }
+}

+ 2 - 0
device-start/src/main/java/com/xy/StartCloud.java

@@ -1,9 +1,11 @@
 package com.xy;
 
+import cn.easyes.starter.register.EsMapperScan;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 
 @CloudApplication
+@EsMapperScan("com.xy.**.mapper")
 @MapperScan("com.xy.**.mapper")
 public class StartCloud {
 

+ 12 - 1
device-start/src/main/resources/bootstrap-uat.yml

@@ -3,4 +3,15 @@ cloud:
   service:
     name: device
     ip: 119.96.213.127
-    port: 9054
+    port: 9051
+
+#xxl-job配置
+xxl:
+  job:
+    executor:
+      appname: device-app
+      ip: ${cloud.service.ip}
+      port: 9061
+
+#雪花ID唯一标识
+workerId: 10

+ 4 - 2
device-start/src/main/resources/bootstrap.yml

@@ -1,16 +1,18 @@
 spring:
   profiles:
     include: cloud
+  mqtt:
+    is-retry: true
 
 server:
-  port: 8002
+  port: 9051
 
 #微服务相关配置
 cloud:
   center:
     url: 119.96.213.127:9007
     config:
-      shared-configs: redis.yaml,mysql.yaml
+      shared-configs: redis.yaml,mysql.yaml,mqtt.yaml,es.yaml
       name: device
   service:
     name: dev-device