Explorar el Código

add 固件升级、固件升级任务

18339543638 hace 4 años
padre
commit
71a5433fa0

+ 3 - 2
jetlinks-manager/device-manager/pom.xml

@@ -23,9 +23,9 @@
 
         <dependency>
             <groupId>cn.hutool</groupId>
-            <artifactId>hutool-json</artifactId>
-            <version>5.5.0</version>
+            <artifactId>hutool-all</artifactId>
         </dependency>
+
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>elasticsearch-component</artifactId>
@@ -56,6 +56,7 @@
             <version>${hsweb.framework.version}</version>
         </dependency>
 
+
         <dependency>
             <groupId>io.r2dbc</groupId>
             <artifactId>r2dbc-h2</artifactId>

+ 145 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceUpgradeHistoryEntity.java

@@ -0,0 +1,145 @@
+package org.jetlinks.community.device.entity;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType;
+import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
+import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
+import org.hswebframework.ezorm.rdb.mapping.annotation.EnumCodec;
+import org.hswebframework.web.api.crud.entity.GenericEntity;
+import org.hswebframework.web.api.crud.entity.RecordCreationEntity;
+import org.hswebframework.web.crud.generator.Generators;
+import org.hswebframework.web.validator.CreateGroup;
+import org.jetlinks.community.device.enums.FirmwareUpgradeState;
+import org.jetlinks.community.device.enums.TaskMode;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Index;
+import javax.persistence.Table;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName DeviceFirmwareEntity.java
+ * @Description TODO
+ * @createTime 2021年08月10日 08:47:00
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Table(name = "dev_firmware_upgrade_history",indexes = {
+    @Index(name = "history_id", columnList = "device_id,task_id,firmware_id",unique = true),
+})
+@Builder
+//@NoArgsConstructor
+public class DeviceUpgradeHistoryEntity extends GenericEntity<String> {
+
+    @Override
+    @GeneratedValue(generator = Generators.SNOW_FLAKE)
+    @Pattern(regexp = "^[0-9a-zA-Z_\\-]+$", message = "ID只能由数字,字母,下划线和中划线组成", groups = CreateGroup.class)
+    @Schema(description = "设备ID(只能由数字,字母,下划线和中划线组成)")
+    public String getId() {
+        return super.getId();
+    }
+
+    @Comment("产品id")
+    @Column(name = "product_id", length = 255)
+    @NotBlank(message = "产品id不能为空", groups = CreateGroup.class)
+    @Schema(description = "产品id")
+    private String productId;
+
+    @Comment("设备id")
+    @Column(name = "device_id", length = 255)
+    @Size(max = 255,message = "固件名称长度不得超过255个字符")
+    @NotBlank(message = "设备id不能为空", groups = CreateGroup.class)
+    @Schema(description = "设备id")
+    private String deviceId;
+
+    @Comment("设备名称")
+    @Column(name = "device_name", length = 255)
+    @Size(max = 255,message = "设备名称不能超过255个字节")
+    @NotBlank(message = "设备名称不能为空", groups = CreateGroup.class)
+    @Schema(description = "设备名称")
+    private String deviceName;
+
+    @Comment("固件id")
+    @Column(name = "firmware_id", length = 255)
+    @NotBlank(message = "固件id不能为空", groups = CreateGroup.class)
+    @Schema(description = "固件id")
+    private String firmwareId;
+
+    @Comment("更新进度")
+    @Column(name = "progress", length = 255,columnDefinition = "0")
+    @Schema(description = "更新进度")
+    private String progress;
+
+    @Comment("任务id")
+    @Column(name = "task_id", length = 255)
+    @NotBlank(message = "任务id不能为空", groups = CreateGroup.class)
+    @Schema(description = "任务id")
+    private String taskId;
+
+    @Comment("错误原因")
+    @Column(name = "error_reason", length = 1024)
+    @Schema(description = "错误原因")
+    private String errorReason;
+
+    @Comment("任务名称")
+    @Column(name = "task_id", length = 255)
+    @NotBlank(message = "任务名称", groups = CreateGroup.class)
+    @Schema(description = "任务名称")
+    private String taskName;
+
+    @Comment("超时时间")
+    @Column(name = "timeout_seconds", length = 255)
+    @NotBlank(message = "超时时间不能为空", groups = CreateGroup.class)
+    @Schema(description = "超时时间")
+    private String timeoutSeconds;
+
+    @Column(name = "version", length = 255)
+    @Size(max = 255,message = "版本号长度不得超过255个字符")
+    @NotBlank(message = "版本号不能为空", groups = CreateGroup.class)
+    @Schema(description = "版本号")
+    private String version;
+
+    @Comment("版本序号")
+    @Column(name = "version_order", length = 255)
+    @Size(max = 255,message = "版本序号长度不得超过255个字符")
+    @NotBlank(message = "版本序号不能为空", groups = CreateGroup.class)
+    @Schema(description = "版本序号")
+    private String versionOrder;
+
+    @Column(name = "create_time", updatable = false)
+    @DefaultValue(generator = Generators.CURRENT_TIME)
+    @Schema(
+        description = "创建时间(只读)"
+        , accessMode = Schema.AccessMode.READ_ONLY
+    )
+    private Long createTime;
+
+    @Column(name = "last_update_time", updatable = false)
+    @Schema(
+        description = "最近更新时间(只读)"
+        , accessMode = Schema.AccessMode.READ_ONLY
+    )
+    private Long lastUpdateTime;
+
+    @Column(name = "state",length = 16)
+    @EnumCodec
+    @ColumnType(javaType = String.class)
+    @NotNull(message = "更新状态不能为空",groups = CreateGroup.class)
+    @Schema(
+        description = "更新状态"
+        ,accessMode = Schema.AccessMode.READ_WRITE
+    )
+    private FirmwareUpgradeState state;
+
+
+}

+ 34 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/enums/FirmwareUpgradeState.java

@@ -0,0 +1,34 @@
+package org.jetlinks.community.device.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.hswebframework.web.dict.Dict;
+import org.hswebframework.web.dict.EnumDict;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName FirmwareUpgradeState.java
+ * @Description TODO
+ * @createTime 2021年08月13日 10:44:00
+ */
+@AllArgsConstructor
+@Dict("firmware-upgrade_state")
+public enum  FirmwareUpgradeState implements EnumDict<String> {
+    waiting("等待升级"),
+    processing("升级中"),
+    failed("升级失败"),
+    finished("升级完成");
+
+    private String text;
+
+    @Override
+    public String getText() {
+        return text;
+    }
+
+    @Override
+    public String getValue() {
+        return name();
+    }
+}

+ 41 - 36
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/writer/TimeSeriesMessageWriterConnector.java

@@ -40,9 +40,14 @@ public class TimeSeriesMessageWriterConnector {
 
     static {
         downMessages=Arrays.asList(READ_PROPERTY,WRITE_PROPERTY,INVOKE_FUNCTION,DISCONNECT,CHILD,
-            READ_FIRMWARE,REQUEST_FIRMWARE,UPGRADE_FIRMWARE,ACKNOWLEDGE,STATE_CHECK);
+            READ_FIRMWARE,
+            REQUEST_FIRMWARE,
+//            UPGRADE_FIRMWARE,
+            ACKNOWLEDGE,STATE_CHECK);
         upMessages=Arrays.asList(REPORT_PROPERTY,EVENT,ONLINE,OFFLINE,REGISTER,
-            UN_REGISTER,DERIVED_METADATA,REPORT_FIRMWARE,UPGRADE_FIRMWARE_PROGRESS,UPDATE_TAG);
+            UN_REGISTER,DERIVED_METADATA,
+//            REPORT_FIRMWARE,
+            UPGRADE_FIRMWARE_PROGRESS,UPDATE_TAG);
     }
     /**
      * 上行消息
@@ -68,40 +73,40 @@ public class TimeSeriesMessageWriterConnector {
         return dataService.saveDeviceMessage(message);
     }
 
-    @PostConstruct
-    public void clusterSubscribe(){
-        //上行主题数据处理
-        clusterManager.getTopic("/device/**").subscribePattern()
-        .doOnNext(message->{
-            String topic = message.getTopic();
-            DeviceMessage deviceMessage= (DeviceMessage) message.getMessage();
-            deviceMessage.addHeader(FIRST,false);
-            deviceMessage.addHeader(ONLY_READ,false);
-            eventBus.publish(topic,deviceMessage).subscribe();
-        }).subscribe();
-    }
-
-
-    /**
-     * 数据下行处理
-     * @param message
-     * @return
-     */
-    @Subscribe(topics = "/device/**", id = "ts-device-message-writer")
-    public Mono<Void> writeTsToDevice(DeviceMessage message) {
-        String deviceId = message.getDeviceId();
-        String productId = String.valueOf(message.getHeader("productId").get());
-        if(downMessages.contains(message.getMessageType())){
-            try {
-                String deviceMessageTopic = DeviceMessageConnector.createDeviceMessageTopic(productId, deviceId, message);
-                disconnect(message);
-
-            }catch (Exception e){
-                log.error("message : {} ,cluster share failed",message);
-            }
-        }
-        return Mono.empty();
-    }
+//    @PostConstruct
+//    public void clusterSubscribe(){
+//        //上行主题数据处理
+//        clusterManager.getTopic("/device/**").subscribePattern()
+//        .doOnNext(message->{
+//            String topic = message.getTopic();
+//            DeviceMessage deviceMessage= (DeviceMessage) message.getMessage();
+//            deviceMessage.addHeader(FIRST,false);
+//            deviceMessage.addHeader(ONLY_READ,false);
+//            eventBus.publish(topic,deviceMessage).subscribe();
+//        }).subscribe();
+//    }
+
+
+//    /**
+//     * 数据下行处理
+//     * @param message
+//     * @return
+//     */
+//    @Subscribe(topics = "/device/**", id = "ts-device-message-writer")
+//    public Mono<Void> writeTsToDevice(DeviceMessage message) {
+//        String deviceId = message.getDeviceId();
+//        String productId = String.valueOf(message.getHeader("productId").get());
+//        if(downMessages.contains(message.getMessageType())){
+//            try {
+//                String deviceMessageTopic = DeviceMessageConnector.createDeviceMessageTopic(productId, deviceId, message);
+//                disconnect(message);
+//
+//            }catch (Exception e){
+//                log.error("message : {} ,cluster share failed",message);
+//            }
+//        }
+//        return Mono.empty();
+//    }
 
 
     //断开连接

+ 185 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalFirmwareUpgradeHistoryService.java

@@ -0,0 +1,185 @@
+package org.jetlinks.community.device.service;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.cron.CronUtil;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.ezorm.rdb.mapping.ReactiveUpdate;
+import org.hswebframework.web.crud.service.GenericReactiveCrudService;
+import org.jetlinks.community.device.entity.DeviceFirmwareEntity;
+import org.jetlinks.community.device.entity.DeviceFirmwareTaskEntity;
+import org.jetlinks.community.device.entity.DeviceInstanceEntity;
+import org.jetlinks.community.device.entity.DeviceUpgradeHistoryEntity;
+import org.jetlinks.community.device.enums.FirmwareUpgradeState;
+import org.jetlinks.community.device.enums.TaskMode;
+import org.jetlinks.community.gateway.annotation.Subscribe;
+import org.jetlinks.core.device.DeviceMessageSender;
+import org.jetlinks.core.device.DeviceOperator;
+import org.jetlinks.core.device.DeviceRegistry;
+import org.jetlinks.core.message.firmware.*;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import javax.management.Query;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName LocalDeviceFirmwareService.java
+ * @Description TODO
+ * @createTime 2021年08月10日 09:26:00
+ */
+@Service
+@AllArgsConstructor
+@Slf4j
+public class LocalFirmwareUpgradeHistoryService extends GenericReactiveCrudService<DeviceUpgradeHistoryEntity, String> {
+    private final LocalDeviceFirmwareTaskService firmwareTaskService;
+    private final LocalDeviceFirmwareService firmwareService;
+    private final LocalDeviceInstanceService deviceService;
+    private final DeviceRegistry registry;
+    public static final Map<String,ScheduledFuture<?>> taskDelayService=new ConcurrentHashMap<>();
+    /**
+     * 上报版本信息
+     * @param message
+     * @return
+     */
+    @Subscribe("/device/*/*/firmware/report")
+    public Mono<Void> createHistory(ReportFirmwareMessage message) {
+        return
+            Mono.zip(
+                registry.getDevice(message.getDeviceId()),
+                firmwareService.createQuery().where(DeviceFirmwareEntity::getProductId, message.getHeader("productId").get()).fetchOne(),
+                //平台推送
+                firmwareTaskService.createQuery()
+                    .where(DeviceFirmwareTaskEntity::getMode,TaskMode.push)
+                    .where(DeviceFirmwareTaskEntity::getProductId, message.getHeader("productId").get()).fetchOne())
+                .doOnNext(tp3 -> {
+                    DeviceOperator operator = tp3.getT1();
+                    DeviceFirmwareEntity firmware = tp3.getT2();
+                    if (!firmware.getVersion().equals(message.getVersion())) {
+                        //如果存在平台推送且版本不一致,则推送升级固件消息,等待升级
+                        UpgradeFirmwareMessage firmwareMessage = new UpgradeFirmwareMessage();
+                        firmwareMessage.setDeviceId(message.getDeviceId());
+                        firmwareMessage.setUrl(firmware.getUrl());
+                        firmwareMessage.setVersion(firmware.getVersion());
+                        firmwareMessage.setSign(firmware.getSign());
+                        firmwareMessage.setSignMethod(firmware.getSignMethod());
+                        firmwareMessage.setTimestamp(System.currentTimeMillis());
+                        operator.messageSender().sendAndForget(firmwareMessage).subscribe();
+                    }
+                }).then();
+    }
+
+    /**
+     * 上报更新进度
+     * @param message
+     * @return
+     */
+    @Subscribe("/device/*/*/firmware/progress")
+    public Mono<Void> handleProcess(UpgradeFirmwareProgressMessage message) {
+        return Mono.just(message)
+            .doOnNext(progress->{
+                String firmwareId = message.getFirmwareId();
+                String version = message.getVersion();
+                ReactiveUpdate<DeviceUpgradeHistoryEntity> upgrade = this.createUpdate()
+                    .where(DeviceUpgradeHistoryEntity::getDeviceId, message.getDeviceId())
+                    .where(DeviceUpgradeHistoryEntity::getFirmwareId, firmwareId)
+                    .where(DeviceUpgradeHistoryEntity::getVersion, version)
+                    .in(DeviceUpgradeHistoryEntity::getState,FirmwareUpgradeState.processing,FirmwareUpgradeState.waiting)
+                    .set(DeviceUpgradeHistoryEntity::getProgress, message.getProgress())
+                    .set(DeviceUpgradeHistoryEntity::getLastUpdateTime,System.currentTimeMillis());
+                boolean complete = message.isComplete();
+                //更新是否结束
+                if(complete){
+                    //判断更新成功或者失败
+                    boolean success = message.isSuccess();
+                    if(success){
+                        upgrade.set(DeviceUpgradeHistoryEntity::getState,FirmwareUpgradeState.finished)
+                            .set(DeviceUpgradeHistoryEntity::getProgress, 100)
+                            .set(DeviceUpgradeHistoryEntity::getErrorReason,null);
+                    }else {
+                        upgrade.set(DeviceUpgradeHistoryEntity::getState,FirmwareUpgradeState.failed)
+                            .set(DeviceUpgradeHistoryEntity::getErrorReason,message.getErrorReason());
+                    }
+                }else {
+                    upgrade.set(DeviceUpgradeHistoryEntity::getState,FirmwareUpgradeState.processing);
+                }
+                upgrade.execute().subscribe();
+            }).doOnNext(progress->{
+                if(message.getProgress()==0){
+                    //设备id+固件id+版本号作为key值
+                    String key=message.getDeviceId()+message.getFirmwareId()+message.getVersion();
+                    //开始更新,创建超时任务
+                    taskDelayService.putIfAbsent(key, Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(
+                        () -> {
+                            String firmwareId = message.getFirmwareId();
+                            String version = message.getVersion();
+                            //更新失败
+                            this.createUpdate()
+                                .where(DeviceUpgradeHistoryEntity::getDeviceId, message.getDeviceId())
+                                .where(DeviceUpgradeHistoryEntity::getFirmwareId, firmwareId)
+                                .where(DeviceUpgradeHistoryEntity::getVersion, version)
+                                .where(DeviceUpgradeHistoryEntity::getState,FirmwareUpgradeState.processing)
+                                .set(DeviceUpgradeHistoryEntity::getState,FirmwareUpgradeState.failed)
+                                .set(DeviceUpgradeHistoryEntity::getErrorReason,"升级超时")
+                                .set(DeviceUpgradeHistoryEntity::getProgress, message.getProgress())
+                                .set(DeviceUpgradeHistoryEntity::getLastUpdateTime,System.currentTimeMillis()).execute().subscribe();
+                            taskDelayService.remove(key);
+                        },
+                        System.currentTimeMillis(), 3L, TimeUnit.SECONDS));
+
+                }
+            })
+            .then();
+    }
+
+    /**
+     * 拉取固件更新,返回更新信息并创建历史更新记录
+     * @param messages
+     * @return
+     */
+    @Subscribe("/device/*/*/firmware/pull")
+    public Mono<Void> pushUpgrade(RequestFirmwareMessage messages) {
+        return registry.getDevice(messages.getDeviceId())
+            .flatMap(operator->{
+                return Mono.zip(operator.getProduct(),
+                    Mono.just(operator.messageSender()),
+                    firmwareService.createQuery()
+                        .where(DeviceFirmwareEntity::getProductId,messages.getHeader("productId").get())
+                        .when("version",messages.getRequestVersion(),value->StrUtil.isNotEmpty(messages.getRequestVersion()),query->query::where)
+                        .fetchOne(),
+                    deviceService.findById(messages.getDeviceId()));
+            })
+            .flatMap(tp4->{
+                //查询当前产品的升级任务
+                DeviceFirmwareEntity firmware = tp4.getT3();
+                return Mono.zip(Mono.just(tp4.getT1()),Mono.just(tp4.getT2()),Mono.just(tp4.getT3()),Mono.just(tp4.getT4()),
+                    firmwareTaskService.createQuery()
+                        .where(DeviceFirmwareTaskEntity::getFirmwareId,firmware.getId())
+                        .where(DeviceFirmwareTaskEntity::getMode, TaskMode.pull.getValue())
+                        .fetchOne());
+            })
+            .doOnNext(tp5->{
+                DeviceFirmwareEntity firmware = tp5.getT3();
+                DeviceMessageSender sender = tp5.getT2();
+                RequestFirmwareMessageReply reply = new RequestFirmwareMessageReply();
+                reply.setTimestamp(System.currentTimeMillis());
+                reply.setDeviceId(messages.getDeviceId());
+                reply.setSign(firmware.getSign());
+                reply.setSignMethod(firmware.getSignMethod());
+                reply.setSize(10L);
+                reply.setUrl(firmware.getUrl());
+                reply.setMessageId(messages.getMessageId());
+                sender.sendAndForget(reply).
+                    subscribe();
+            }).then();
+    }
+}

+ 19 - 5
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceCategoryController.java

@@ -8,8 +8,12 @@ import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
 import org.hswebframework.web.exception.BusinessException;
 import org.jetlinks.community.device.entity.DeviceCategory;
+import org.jetlinks.community.device.entity.DeviceProductEntity;
 import org.jetlinks.community.device.service.DeviceCategoryService;
+import org.jetlinks.community.device.service.LocalDeviceProductService;
+import org.reactivestreams.Subscription;
 import org.springframework.web.bind.annotation.*;
+import reactor.core.CoreSubscriber;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
@@ -23,6 +27,7 @@ import java.util.function.Function;
 public class DeviceCategoryController{
 
 
+    private final LocalDeviceProductService productService;
     private final DeviceCategoryService service;
 
     @PostMapping("/add")
@@ -37,12 +42,21 @@ public class DeviceCategoryController{
     @DeleteMapping("/{id}")
     @Operation(summary = "删除目录")
     public Mono<?> remove(@PathVariable @Parameter(description = "设备ID") String id){
-        return this.service.createDelete()
-            .where(DeviceCategory::getId,id)
-            .execute()
-            .then();
+        return productService.createQuery()
+            .where(DeviceProductEntity::getClassifiedId,id)
+            .count()
+            .map(count->{
+                if("0".equals(String.valueOf(0))){
+                    return this.service.createDelete()
+                        .where(DeviceCategory::getId,id)
+                        .execute()
+                        .subscribe();
+                }
+                return Mono.error(new BusinessException("该目录已被绑定产品,不可删除")) ;
+            }).thenReturn(Function.identity());
     }
 
+
     @PutMapping
     @Operation(summary = "更新目录")
     public Mono<Void> updata(@RequestBody Mono<DeviceCategory> payload){
@@ -68,7 +82,7 @@ public class DeviceCategoryController{
     public Flux<DeviceCategory> getAllCategory() {
         return this.service.createQuery()
             .fetch();
-    //        return Flux.fromIterable(statics);
+        //        return Flux.fromIterable(statics);
     }
 
     @GetMapping("/_tree")

+ 52 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceFirmwareUpgradeHistoryController.java

@@ -0,0 +1,52 @@
+package org.jetlinks.community.device.web;
+
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.authorization.annotation.Resource;
+import org.hswebframework.web.crud.service.ReactiveCrudService;
+import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
+import org.jetlinks.community.device.entity.DeviceFirmwareTaskEntity;
+import org.jetlinks.community.device.entity.DeviceUpgradeHistoryEntity;
+import org.jetlinks.community.device.service.LocalDeviceFirmwareTaskService;
+import org.jetlinks.community.device.service.LocalFirmwareUpgradeHistoryService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName DeviceFirmwareController.java
+ * @Description TODO
+ * @createTime 2021年08月10日 09:28:00
+ */
+@RestController
+@RequestMapping({"/firmware/upgrade/history","/firmware-upgrade-history"})
+@Authorize
+@Resource(id = "/firmware-upgrade-history", name = "设备固件升级记录")
+@Slf4j
+@AllArgsConstructor
+@Tag(name = "设备固件升级记录接口")
+public class DeviceFirmwareUpgradeHistoryController implements
+    ReactiveServiceCrudController<DeviceUpgradeHistoryEntity, String> {
+    private final LocalFirmwareUpgradeHistoryService historyService;
+
+    @Override
+    public ReactiveCrudService<DeviceUpgradeHistoryEntity, String> getService() {
+        return historyService;
+    }
+
+    //todo 有设备在进行升级时不可删除
+    @Override
+    public Mono<DeviceUpgradeHistoryEntity> delete(String id) {
+        return null;
+    }
+
+    //todo 有设备在进行升级时不可修改
+    @Override
+    public Mono<Boolean> update(String id, Mono<DeviceUpgradeHistoryEntity> payload) {
+        return null;
+    }
+}

+ 1 - 1
jetlinks-standalone/src/main/resources/application.yml

@@ -15,6 +15,7 @@ spring:
   resources:
     static-locations: file:./static/,/,classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/, classpath:/public/
   redis:
+    host: 192.168.104.114
 #    host: 1.15.89.83
     port: 6379
     password: 6E6985E1F7CB40F24A\.
@@ -23,7 +24,6 @@ spring:
         max-active: 1024
     timeout: 20s
     serializer: jdk # 设置fst时,redis key使用string序列化,value使用 fst序列化.
-    host: 192.168.104.114
   #    database: 3
   #        max-wait: 10s
   r2dbc:

+ 21 - 0
jetlinks-standalone/src/test/java/org/jetlinks/community/network/manager/web/GateWayTest.java

@@ -3,8 +3,12 @@ package org.jetlinks.community.network.manager.web;
 import io.vertx.core.Vertx;
 import io.vertx.mqtt.MqttServerOptions;
 import lombok.extern.slf4j.Slf4j;
+import org.checkerframework.checker.nullness.Opt;
 import org.checkerframework.checker.units.qual.A;
 import org.hswebframework.web.exception.NotFoundException;
+import org.jetlinks.community.device.entity.DeviceFirmwareEntity;
+import org.jetlinks.community.device.service.LocalDeviceFirmwareService;
+import org.jetlinks.community.device.service.LocalDeviceInstanceService;
 import org.jetlinks.community.gateway.DeviceGatewayManager;
 import org.jetlinks.community.network.NetworkManager;
 import org.jetlinks.community.network.manager.entity.DeviceGatewayEntity;
@@ -28,6 +32,7 @@ import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Function;
 
@@ -38,6 +43,9 @@ import java.util.function.Function;
  * @Description TODO
  * @createTime 2021年06月29日 14:25:00
  */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = JetLinksApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)
 public class GateWayTest {
     @Autowired
     private DeviceGatewayService deviceGatewayService;
@@ -55,6 +63,19 @@ public class GateWayTest {
 
     static MqttServer mqttServer;
 
+    @Autowired
+    private LocalDeviceFirmwareService firmwareService;
+    @Autowired
+    private LocalDeviceInstanceService instanceService;
+
+    @Test
+    public void test(){
+        Optional<DeviceFirmwareEntity> deviceFirmwareEntity = firmwareService.createQuery().where(DeviceFirmwareEntity::getProductId, Optional.of(3))
+            .fetchOne()
+            .blockOptional();
+
+        System.out.println(deviceFirmwareEntity.get());
+    }
     public static void main(String[] args) throws InterruptedException {
         VertxMqttServerProvider mqttServerManager = new VertxMqttServerProvider(id -> Mono.empty(), vertx);