Merge remote-tracking branch 'origin/master'

This commit is contained in:
zhouhao 2023-05-08 16:45:36 +08:00
commit a2cd2688cb
8 changed files with 166 additions and 42 deletions

View File

@ -6,7 +6,8 @@
![Version](https://img.shields.io/badge/version-1.20--RELEASE-brightgreen)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e8d527d692c24633aba4f869c1c5d6ad)](https://app.codacy.com/gh/jetlinks/jetlinks-community?utm_source=github.com&utm_medium=referral&utm_content=jetlinks/jetlinks-community&utm_campaign=Badge_Grade_Settings)
[![OSCS Status](https://www.oscs1024.com/platform/badge/jetlinks/jetlinks-community.svg?size=small)](https://www.oscs1024.com/project/jetlinks/jetlinks-community?ref=badge_small)
![jetlinks](https://visitor-badge.glitch.me/badge?page_id=jetlinks)
[![star](https://img.shields.io/github/stars/jetlinks/jetlinks-community?style=social)](https://github.com/jetlinks/jetlinks-community)
[![star](https://gitee.com/jetlinks/jetlinks-community/badge/star.svg?theme=gvp)](https://gitee.com/jetlinks/jetlinks-community/stargazers)
[![QQ①群2021514](https://img.shields.io/badge/QQ①群-2021514-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=LGf0OPQqvLGdJIZST3VTcypdVWhdfAOG&jump_from=webapi)
[![QQ②群324606263](https://img.shields.io/badge/QQ②群-324606263-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=IMas2cH-TNsYxUcY8lRbsXqPnA2sGHYQ&jump_from=webapi)

View File

@ -48,7 +48,7 @@ services:
POSTGRES_DB: jetlinks
TZ: Asia/Shanghai
ui:
image: registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-pro:2.0.0
image: registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.1.0-SNAPSHOT
container_name: jetlinks-ce-ui
ports:
- 9000:80
@ -59,7 +59,7 @@ services:
links:
- jetlinks:jetlinks
jetlinks:
image: registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-standalone:2.0.0-SNAPSHOT
image: registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-standalone:2.1.0-SNAPSHOT
container_name: jetlinks-ce
ports:

View File

@ -1,6 +1,7 @@
package org.jetlinks.community.notify.sms.aliyun;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import lombok.Getter;
import lombok.Setter;
import org.jetlinks.core.metadata.types.StringType;
@ -64,7 +65,10 @@ public class AliyunSmsTemplate extends AbstractTemplate<AliyunSmsTemplate> {
}
public String createTtsParam(Map<String, Object> ctx) {
return JSON.toJSONString(ctx);
Map<String, VariableDefinition> variables = getVariables();
return JSON.toJSONString(Maps.filterEntries(
renderMap(ctx),
e -> variables.containsKey(e.getKey())));
}
@Override

View File

@ -0,0 +1,35 @@
package org.jetlinks.community.device.response;
import lombok.*;
import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult;
/**
* @see ImportDeviceInstanceResult 结构一致方便前端处理
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ResetDeviceConfigurationResult {
private SaveResult result;
private boolean success;
private String message;
@Generated
public static ResetDeviceConfigurationResult success(SaveResult result) {
return new ResetDeviceConfigurationResult(result, true, null);
}
@Generated
public static ResetDeviceConfigurationResult error(String message) {
return new ResetDeviceConfigurationResult(null, false, message);
}
@Generated
public static ResetDeviceConfigurationResult error(Throwable message) {
return error(message.getMessage());
}
}

View File

@ -7,11 +7,15 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.Nonnull;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
@Component
@Slf4j
@ -80,6 +84,15 @@ public class DefaultDeviceConfigMetadataManager implements DeviceConfigMetadataM
.sort(Comparator.comparing(ConfigMetadata::getName));
}
@Override
public Mono<Set<String>> getProductConfigMetadataProperties(String productId) {
return this
.getProductConfigMetadata(productId)
.flatMapIterable(ConfigMetadata::getProperties)
.map(ConfigPropertyMetadata::getProperty)
.collect(Collectors.toSet());
}
@Override
public Object postProcessAfterInitialization(@Nonnull Object bean, @Nonnull String beanName) {
if (bean instanceof DeviceConfigMetadataSupplier) {

View File

@ -6,6 +6,9 @@ import org.jetlinks.community.device.spi.DeviceConfigMetadataSupplier;
import org.jetlinks.core.message.codec.Transport;
import org.jetlinks.core.metadata.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Set;
/**
@ -75,6 +78,13 @@ public interface DeviceConfigMetadataManager {
String typeId,
ConfigScope... scopes);
/**
* 根据产品ID获取产品所需配置信息
*
* @param productId 产品ID
* @return 配置property集合
*/
Mono<Set<String>> getProductConfigMetadataProperties(String productId);
/**
* 根据产品ID和网关ID获取配置信息

View File

@ -17,7 +17,17 @@ import org.hswebframework.web.exception.I18nSupportException;
import org.hswebframework.web.exception.TraceSourceException;
import org.hswebframework.web.i18n.LocaleUtils;
import org.hswebframework.web.id.IDGenerator;
import org.jetlinks.community.device.entity.*;
import org.jetlinks.community.device.enums.DeviceState;
import org.jetlinks.community.device.events.DeviceDeployedEvent;
import org.jetlinks.community.device.events.DeviceUnregisterEvent;
import org.jetlinks.community.device.response.DeviceDeployResult;
import org.jetlinks.community.device.response.DeviceDetail;
import org.jetlinks.community.device.response.ResetDeviceConfigurationResult;
import org.jetlinks.community.relation.RelationObjectProvider;
import org.jetlinks.community.relation.service.RelationService;
import org.jetlinks.community.relation.service.response.RelatedInfo;
import org.jetlinks.community.utils.ErrorUtils;
import org.jetlinks.core.device.DeviceConfigKey;
import org.jetlinks.core.device.DeviceOperator;
import org.jetlinks.core.device.DeviceProductOperator;
@ -36,15 +46,6 @@ import org.jetlinks.core.metadata.ConfigMetadata;
import org.jetlinks.core.metadata.DeviceMetadata;
import org.jetlinks.core.metadata.MergeOption;
import org.jetlinks.core.utils.CyclicDependencyChecker;
import org.jetlinks.community.device.entity.*;
import org.jetlinks.community.device.enums.DeviceState;
import org.jetlinks.community.device.events.DeviceDeployedEvent;
import org.jetlinks.community.device.events.DeviceUnregisterEvent;
import org.jetlinks.community.device.response.DeviceDeployResult;
import org.jetlinks.community.relation.RelationObjectProvider;
import org.jetlinks.community.relation.service.RelationService;
import org.jetlinks.community.relation.service.response.RelatedInfo;
import org.jetlinks.community.utils.ErrorUtils;
import org.jetlinks.reactor.ql.utils.CastUtils;
import org.jetlinks.supports.official.JetLinksDeviceMetadataCodec;
import org.reactivestreams.Publisher;
@ -121,6 +122,47 @@ public class LocalDeviceInstanceService extends GenericReactiveCrudService<Devic
.as(super::save);
}
private Flux<DeviceInstanceEntity> findByProductId(String productId) {
return createQuery()
.and(DeviceInstanceEntity::getProductId, productId)
.fetch();
}
private Set<String> getProductConfigurationProperties(DeviceProductEntity product) {
if (MapUtils.isNotEmpty(product.getConfiguration())) {
return product.getConfiguration()
.keySet();
}
return new HashSet<>();
}
private Mono<Map<String, Object>> resetConfiguration(DeviceProductEntity product, DeviceInstanceEntity device) {
return metadataManager
.getProductConfigMetadataProperties(product.getId())
.defaultIfEmpty(getProductConfigurationProperties(product))
.flatMap(set -> {
if (set.size() > 0) {
if (MapUtils.isNotEmpty(device.getConfiguration())) {
set.forEach(device.getConfiguration()::remove);
}
//重置注册中心里的配置
return registry
.getDevice(device.getId())
.flatMap(opts -> opts.removeConfigs(set))
.then();
}
return Mono.empty();
})
.then(
//更新数据库
createUpdate()
.set(device::getConfiguration)
.where(device::getId)
.execute()
)
.then(Mono.fromSupplier(device::getConfiguration));
}
/**
* 重置设备配置
*
@ -135,36 +177,37 @@ public class LocalDeviceInstanceService extends GenericReactiveCrudService<Devic
.flatMap(tp2 -> {
DeviceProductEntity product = tp2.getT2();
DeviceInstanceEntity device = tp2.getT1();
return Mono
.defer(() -> {
if (MapUtils.isNotEmpty(product.getConfiguration())) {
if (MapUtils.isNotEmpty(device.getConfiguration())) {
product.getConfiguration()
.keySet()
.forEach(device.getConfiguration()::remove);
}
//重置注册中心里的配置
return registry
.getDevice(deviceId)
.flatMap(opts -> opts.removeConfigs(product.getConfiguration().keySet()))
.then();
}
return Mono.empty();
})
.then(
Mono.defer(() -> {
//更新数据库
return createUpdate()
.when(device.getConfiguration() != null, update -> update.set(device::getConfiguration))
.when(device.getConfiguration() == null, update -> update.setNull(DeviceInstanceEntity::getConfiguration))
.where(device::getId)
.execute();
})
)
.then(Mono.fromSupplier(device::getConfiguration));
return resetConfiguration(product, device);
})
.defaultIfEmpty(Collections.emptyMap())
;
.defaultIfEmpty(Collections.emptyMap());
}
public Mono<Long> resetConfiguration(Flux<String> payload) {
return payload
.flatMap(deviceId -> resetConfiguration(deviceId)).count();
}
/**
* 重置设备配置信息(根据产品批量重置性能欠佳慎用)
*
* @param productId 产品ID
* @return 数量
*/
public Flux<ResetDeviceConfigurationResult> resetConfigurationByProductId(String productId) {
return deviceProductService
.findById(productId)
.flatMapMany(product -> this
.findByProductId(productId)
.flatMap(device -> {
return resetConfiguration(product, device)
.thenReturn(ResetDeviceConfigurationResult
.success(SaveResult.of(0, 1)))
.onErrorResume(throwable -> {
String message = device.getId() + ":" + throwable.getMessage();
return Mono.just(ResetDeviceConfigurationResult.error(message));
});
})
);
}
/**

View File

@ -31,6 +31,7 @@ import org.jetlinks.community.device.enums.DeviceState;
import org.jetlinks.community.device.response.DeviceDeployResult;
import org.jetlinks.community.device.response.DeviceDetail;
import org.jetlinks.community.device.response.ImportDeviceInstanceResult;
import org.jetlinks.community.device.response.ResetDeviceConfigurationResult;
import org.jetlinks.community.device.service.DeviceConfigMetadataManager;
import org.jetlinks.community.device.service.LocalDeviceInstanceService;
import org.jetlinks.community.device.service.LocalDeviceProductService;
@ -205,6 +206,23 @@ public class DeviceInstanceController implements
return service.resetConfiguration(deviceId);
}
@PutMapping("/configuration/_reset/ids")
@SaveAction
@Operation(summary = "重置设备配置信息(根据设备ID批量重置性能欠佳慎用)")
public Mono<Long> resetConfigurationBatch(@RequestBody Flux<String> payload) {
return service.resetConfiguration(payload);
}
@GetMapping(value = "/configuration/_reset/{productId:.+}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ResourceAction(
id = "batchResetConf",
name = "批量重置设备配置信息"
)
@Operation(summary = "重置设备配置信息(根据产品批量重置,性能欠佳,慎用)")
public Flux<ResetDeviceConfigurationResult> resetConfigurationBatch(@PathVariable @Parameter(description = "产品ID") String productId) {
return service.resetConfigurationByProductId(productId);
}
//批量激活设备
@GetMapping(value = "/deploy", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@SaveAction