From 4a9977903e101b6be05c4c168a796dc726ae4d16 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 28 Sep 2022 10:03:52 +0800 Subject: [PATCH 01/50] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index b1f0f954..53d991af 100644 --- a/pom.xml +++ b/pom.xml @@ -516,12 +516,18 @@ aliyun-nexus aliyun https://maven.aliyun.com/nexus/content/groups/public/ + + false + hsweb-nexus Nexus Release Repository https://nexus.hsweb.me/content/groups/public/ + + false + true always -- Gitee From 4c18ef264ff733bc8d1406c895c6576d7088093d Mon Sep 17 00:00:00 2001 From: zhouhao Date: Sun, 9 Oct 2022 13:53:07 +0800 Subject: [PATCH 02/50] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E6=B1=A0=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device/MqttServerDeviceGateway.java | 20 ++----------------- .../server/vertx/VertxMqttServerProvider.java | 18 ++++++++++------- .../network/tcp/server/TcpServerProvider.java | 17 +++++++++------- 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/gateway/device/MqttServerDeviceGateway.java b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/gateway/device/MqttServerDeviceGateway.java index b4e5e5a8..d3f32539 100644 --- a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/gateway/device/MqttServerDeviceGateway.java +++ b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/gateway/device/MqttServerDeviceGateway.java @@ -1,13 +1,9 @@ package org.jetlinks.community.network.mqtt.gateway.device; import io.netty.handler.codec.mqtt.MqttConnectReturnCode; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.hswebframework.web.logger.ReactiveLogger; import org.jetlinks.community.gateway.AbstractDeviceGateway; -import org.jetlinks.community.gateway.DeviceGateway; -import org.jetlinks.community.gateway.monitor.DeviceGatewayMonitor; -import org.jetlinks.community.gateway.monitor.GatewayMonitors; import org.jetlinks.community.gateway.monitor.MonitorSupportDeviceGateway; import org.jetlinks.community.network.DefaultNetworkType; import org.jetlinks.community.network.NetworkType; @@ -19,32 +15,23 @@ import org.jetlinks.community.utils.SystemUtils; import org.jetlinks.core.ProtocolSupport; import org.jetlinks.core.device.*; import org.jetlinks.core.device.session.DeviceSessionManager; -import org.jetlinks.core.message.CommonDeviceMessage; -import org.jetlinks.core.message.CommonDeviceMessageReply; import org.jetlinks.core.message.DeviceMessage; -import org.jetlinks.core.message.Message; import org.jetlinks.core.message.codec.DefaultTransport; import org.jetlinks.core.message.codec.FromDeviceMessageContext; import org.jetlinks.core.message.codec.MqttMessage; import org.jetlinks.core.message.codec.Transport; import org.jetlinks.core.server.session.DeviceSession; import org.jetlinks.core.server.session.KeepOnlineSession; -import org.jetlinks.core.server.session.ReplaceableDeviceSession; import org.jetlinks.core.trace.DeviceTracer; import org.jetlinks.core.trace.FluxTracer; -import org.jetlinks.core.trace.MonoTracer; import org.jetlinks.supports.server.DecodedClientMessageHandler; import org.springframework.util.StringUtils; import reactor.core.Disposable; -import reactor.core.publisher.EmitterProcessor; import reactor.core.publisher.Flux; -import reactor.core.publisher.FluxSink; import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; import reactor.util.function.Tuple3; import reactor.util.function.Tuples; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.LongAdder; import java.util.function.Function; @@ -114,7 +101,6 @@ class MqttServerDeviceGateway extends AbstractDeviceGateway implements MonitorSu } return isStarted(); }) - .publishOn(Schedulers.parallel()) //处理mqtt连接请求 .flatMap(this::handleConnection) //处理认证结果 @@ -169,8 +155,7 @@ class MqttServerDeviceGateway extends AbstractDeviceGateway implements MonitorSu monitor.rejected(); //应答SERVER_UNAVAILABLE connection.reject(MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE); - })) - .subscribeOn(Schedulers.parallel()); + })); } //处理认证结果 @@ -306,8 +291,7 @@ class MqttServerDeviceGateway extends AbstractDeviceGateway implements MonitorSu .toJSONString()))) //发生错误不中断流 .onErrorResume((err) -> Mono.empty()) - .then() - .subscribeOn(Schedulers.parallel()); + .then(); } private Mono handleMessage(DeviceOperator mainDevice, diff --git a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttServerProvider.java b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttServerProvider.java index 48e308e1..daba798d 100644 --- a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttServerProvider.java +++ b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttServerProvider.java @@ -53,13 +53,17 @@ public class VertxMqttServerProvider implements NetworkProvider { - if (result.succeeded()) { - log.debug("startup mqtt server [{}] on port :{} ", properties.getId(), result.result().actualPort()); - } else { - log.warn("startup mqtt server [{}] error ", properties.getId(), result.cause()); - } - }); + vertx + .nettyEventLoopGroup() + .execute(()->{ + instance.listen(result -> { + if (result.succeeded()) { + log.debug("startup mqtt server [{}] on port :{} ", properties.getId(), result.result().actualPort()); + } else { + log.warn("startup mqtt server [{}] error ", properties.getId(), result.cause()); + } + }); + }); } } diff --git a/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/server/TcpServerProvider.java b/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/server/TcpServerProvider.java index b07f240a..51f049b3 100644 --- a/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/server/TcpServerProvider.java +++ b/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/server/TcpServerProvider.java @@ -80,13 +80,16 @@ public class TcpServerProvider implements NetworkProvider { // 多个server listen同一个端口,每个client连接的时候vertx会分配 // 一个connection只能在一个server中处理 for (NetServer netServer : instances) { - netServer.listen(properties.createSocketAddress(), result -> { - if (result.succeeded()) { - log.info("tcp server startup on {}", result.result().actualPort()); - } else { - log.error("startup tcp server error", result.cause()); - } - }); + vertx.nettyEventLoopGroup() + .execute(()->{ + netServer.listen(properties.createSocketAddress(), result -> { + if (result.succeeded()) { + log.info("tcp server startup on {}", result.result().actualPort()); + } else { + log.error("startup tcp server error", result.cause()); + } + }); + }); } } -- Gitee From d5f8a6f7b073a6704c22b1430c3f2d8194fa17e9 Mon Sep 17 00:00:00 2001 From: vvsd <40269480+vvsd@users.noreply.github.com> Date: Wed, 12 Oct 2022 15:21:39 +0800 Subject: [PATCH 03/50] update org.bouncycastle:bcprov-jdk15on 1.67 to 1.69 --- .../network-component/network-core/pom.xml | 6 ++---- pom.xml | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/jetlinks-components/network-component/network-core/pom.xml b/jetlinks-components/network-component/network-core/pom.xml index 0d9138ed..11969e20 100644 --- a/jetlinks-components/network-component/network-core/pom.xml +++ b/jetlinks-components/network-component/network-core/pom.xml @@ -1,7 +1,5 @@ - + network-component org.jetlinks.community @@ -32,7 +30,7 @@ org.bouncycastle bcprov-jdk15on - 1.67 + 1.69 diff --git a/pom.xml b/pom.xml index 53d991af..19bd5037 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 org.jetlinks.community @@ -208,7 +206,7 @@ org.bouncycastle bcprov-jdk15on - 1.70 + 1.69 @@ -556,4 +554,4 @@ https://maven.aliyun.com/nexus/content/groups/public/ - + \ No newline at end of file -- Gitee From eda3a24a805cdc5974a0c645f1ced0810cb928c6 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 24 Oct 2022 11:12:32 +0800 Subject: [PATCH 04/50] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AD=90=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E4=BC=9A=E8=AF=9D=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/utils/DeviceGatewayHelper.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/jetlinks-components/network-component/network-core/src/main/java/org/jetlinks/community/network/utils/DeviceGatewayHelper.java b/jetlinks-components/network-component/network-core/src/main/java/org/jetlinks/community/network/utils/DeviceGatewayHelper.java index 565c6220..ad130d8e 100644 --- a/jetlinks-components/network-component/network-core/src/main/java/org/jetlinks/community/network/utils/DeviceGatewayHelper.java +++ b/jetlinks-components/network-component/network-core/src/main/java/org/jetlinks/community/network/utils/DeviceGatewayHelper.java @@ -16,6 +16,7 @@ import reactor.core.publisher.Mono; import reactor.util.context.Context; import java.time.Duration; +import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -121,8 +122,16 @@ public class DeviceGatewayHelper { .createOrUpdateSession(childrenId, children, child -> Mono.just(new ChildrenDeviceSession(childrenId, parentSession, child)), - Mono::empty)); - + Mono::empty) + .doOnNext(session -> { + if (session.isWrapFrom(ChildrenDeviceSession.class)) { + ChildrenDeviceSession childrenSession = session.unwrap(ChildrenDeviceSession.class); + //网关发生变化,替换新的上级会话 + if (!Objects.equals(deviceId, childrenSession.getParent().getDeviceId())) { + childrenSession.replaceWith(parentSession); + } + } + })); //子设备注册 if (isDoRegister(children)) { -- Gitee From c8d8926b0f5e35447e91d5c1982c2b3cce5c2f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8?= Date: Mon, 24 Oct 2022 17:17:59 +0800 Subject: [PATCH 05/50] Update maven.yml --- .github/workflows/maven.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 5ddd6349..6915efa9 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,7 +1,8 @@ name: Auto Deploy Docker -on: [push] - +on: + push: + branches: [ "master","2.0" ] jobs: build: -- Gitee From c939f28248df347299a9b70cc413281ac743f61b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 17:22:57 +0800 Subject: [PATCH 06/50] Bump commons-text from 1.9 to 1.10.0 (#210) Bumps commons-text from 1.9 to 1.10.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-text dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- jetlinks-components/network-component/tcp-component/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jetlinks-components/network-component/tcp-component/pom.xml b/jetlinks-components/network-component/tcp-component/pom.xml index c654146c..8e3df1f1 100644 --- a/jetlinks-components/network-component/tcp-component/pom.xml +++ b/jetlinks-components/network-component/tcp-component/pom.xml @@ -33,7 +33,7 @@ org.apache.commons commons-text - 1.9 + 1.10.0 diff --git a/pom.xml b/pom.xml index 19bd5037..fd04eb4f 100644 --- a/pom.xml +++ b/pom.xml @@ -410,7 +410,7 @@ org.apache.commons commons-text - 1.9 + 1.10.0 -- Gitee From 3749e9e06d7d3dd33ee000460405ff9b540cd6c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 17:23:24 +0800 Subject: [PATCH 07/50] Bump commons-text (#209) Bumps commons-text from 1.9 to 1.10.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-text dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> -- Gitee From 4c86f9d971657e523c3b7e0fd990beebbbc6b6e8 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 31 Oct 2022 10:08:07 +0800 Subject: [PATCH 08/50] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/DeviceMessageBusinessHandler.java | 97 +++++++++++++++---- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java index 4c9b3c63..97e1b876 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java @@ -1,15 +1,19 @@ package org.jetlinks.community.device.service; import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; import org.jetlinks.community.PropertyConstants; +import org.jetlinks.community.buffer.PersistenceBuffer; import org.jetlinks.community.device.entity.DeviceInstanceEntity; import org.jetlinks.community.device.entity.DeviceTagEntity; -import org.jetlinks.community.device.enums.DeviceFeature; import org.jetlinks.community.device.enums.DeviceState; import org.jetlinks.community.gateway.annotation.Subscribe; +import org.jetlinks.community.utils.ErrorUtils; import org.jetlinks.core.device.DeviceConfigKey; import org.jetlinks.core.device.DeviceOperator; import org.jetlinks.core.device.DeviceRegistry; @@ -18,17 +22,26 @@ import org.jetlinks.core.event.Subscription; import org.jetlinks.core.message.*; import org.jetlinks.core.metadata.DeviceMetadata; import org.jetlinks.core.utils.FluxUtils; +import org.jetlinks.core.utils.Reactors; import org.jetlinks.reactor.ql.utils.CastUtils; import org.jetlinks.supports.official.JetLinksDeviceMetadataCodec; +import org.springframework.dao.QueryTimeoutException; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import reactor.core.Disposable; +import reactor.core.Disposables; import reactor.core.publisher.BufferOverflowStrategy; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.time.Duration; import java.util.Date; import java.util.HashMap; @@ -51,6 +64,8 @@ public class DeviceMessageBusinessHandler { private final EventBus eventBus; + private final Disposable.Composite disposable = Disposables.composite(); + /** * 自动注册设备信息 *

@@ -285,6 +300,40 @@ public class DeviceMessageBusinessHandler { } + + @AllArgsConstructor + @NoArgsConstructor + @Getter + @Setter + public static class StateBuf implements Externalizable { + //有效期一小时 + static long expires = Duration.ofHours(1).toMillis(); + + private String id; + private long time; + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(id); + out.writeLong(time); + } + + @Override + public void readExternal(ObjectInput in) throws IOException { + id = in.readUTF(); + time = in.readLong(); + } + + public boolean isEffective() { + return System.currentTimeMillis() - time < expires; + } + } + + @PreDestroy + public void shutdown() { + disposable.dispose(); + } + @PostConstruct public void init() { @@ -295,22 +344,36 @@ public class DeviceMessageBusinessHandler { .justLocal()//只订阅本地 .build(); - //订阅设备上下线消息,同步数据库中的设备状态, - //最小间隔800毫秒,最大缓冲数量500,最长间隔2秒. - //如果2条消息间隔大于0.8秒则不缓冲直接更新 - //否则缓冲,数量超过500后批量更新 - //无论缓冲区是否超过500条,都每2秒更新一次. - FluxUtils.bufferRate(eventBus - .subscribe(subscription, DeviceMessage.class) - .map(DeviceMessage::getDeviceId), - 800, Integer.getInteger("device.state.sync.batch", 500), Duration.ofSeconds(2)) - .onBackpressureBuffer(64, - list -> log.warn("无法处理更多设备状态同步!"), - BufferOverflowStrategy.DROP_OLDEST) - .publishOn(Schedulers.boundedElastic(), 64) - .concatMap(list -> deviceService.syncStateBatch(Flux.just(list), false).map(List::size)) - .onErrorContinue((err, obj) -> log.error(err.getMessage(), err)) - .subscribe((i) -> log.info("同步设备状态成功:{}", i)); + //缓冲同步设备上线信息,在突发大量上下线的情况,减少数据库的压力 + PersistenceBuffer buffer = + new PersistenceBuffer<>( + "./data/device-state-buffer", + "device-state.queue", + StateBuf::new, + flux -> deviceService + .syncStateBatch(flux + .filter(StateBuf::isEffective) + .map(StateBuf::getId) + .distinct() + .collectList() + .flux(), false) + .then(Reactors.ALWAYS_FALSE)) + .name("device-state-synchronizer") + .parallelism(1) + .bufferTimeout(Duration.ofSeconds(1)) + .retryWhenError(e -> ErrorUtils + .hasException(e, + IOException.class, + QueryTimeoutException.class)) + .bufferSize(1000); + + buffer.start(); + + disposable.add(eventBus + .subscribe(subscription, DeviceMessage.class) + .subscribe(msg -> buffer.write(new StateBuf(msg.getDeviceId(), msg.getTimestamp())))); + + disposable.add(buffer); } -- Gitee From 812ecd26b3e5aa25e62eaed00273724542bd2c9a Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 1 Nov 2022 10:23:25 +0800 Subject: [PATCH 09/50] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E4=BC=9A=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PersistenceDeviceSessionManager.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/jetlinks-components/configure-component/src/main/java/org/jetlinks/community/configure/device/PersistenceDeviceSessionManager.java b/jetlinks-components/configure-component/src/main/java/org/jetlinks/community/configure/device/PersistenceDeviceSessionManager.java index cbbfa660..d92391db 100644 --- a/jetlinks-components/configure-component/src/main/java/org/jetlinks/community/configure/device/PersistenceDeviceSessionManager.java +++ b/jetlinks-components/configure-component/src/main/java/org/jetlinks/community/configure/device/PersistenceDeviceSessionManager.java @@ -23,6 +23,7 @@ import reactor.core.publisher.Mono; import javax.annotation.Nonnull; import java.io.File; +import java.time.Duration; import java.util.function.Supplier; @Slf4j @@ -35,6 +36,10 @@ public class PersistenceDeviceSessionManager extends ClusterDeviceSessionManager @Setter private String filePath; + @Getter + @Setter + private Duration flushInterval = Duration.ofMinutes(10); + public PersistenceDeviceSessionManager(RpcManager rpcManager) { super(rpcManager); } @@ -72,6 +77,24 @@ public class PersistenceDeviceSessionManager extends ClusterDeviceSessionManager } repository = initStore(filePath); + if (!flushInterval.isZero() && !flushInterval.isNegative()) { + disposable.add( + Flux + .interval(flushInterval) + .onBackpressureDrop() + .concatMap(ignore -> Flux + .fromIterable(localSessions.values()) + .mapNotNull(ref -> { + if (ref.loaded != null && ref.loaded.isWrapFrom(PersistentSession.class)) { + return ref.loaded.unwrap(PersistentSession.class); + } + return null; + }) + .as(this::tryPersistent), 1) + .subscribe() + ); + } + disposable.add( listenEvent(event -> { //移除持久化的会话 @@ -95,6 +118,7 @@ public class PersistenceDeviceSessionManager extends ClusterDeviceSessionManager .map(ref -> ref.loaded.unwrap(PersistentSession.class)) .as(this::tryPersistent) .block(); + repository.store.compactMoveChunks(); repository.store.close(); } @@ -133,10 +157,10 @@ public class PersistenceDeviceSessionManager extends ClusterDeviceSessionManager .toSession(registry.get()) .doOnNext(session -> { log.debug("resume session[{}]", session.getDeviceId()); - localSessions.putIfAbsent(session.getDeviceId(), new DeviceSessionRef( - session.getDeviceId(), - this, - session)); + localSessions.putIfAbsent(session.getDeviceId(), + new DeviceSessionRef(session.getDeviceId(), + this, + session)); }) .onErrorResume((err) -> { log.debug("resume session[{}] error", entity.getDeviceId(), err); -- Gitee From 7540ab9caca1f9db99b14b74824e01736586536b Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 2 Nov 2022 16:58:12 +0800 Subject: [PATCH 10/50] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtcp=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/network/tcp/client/VertxTcpClient.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/client/VertxTcpClient.java b/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/client/VertxTcpClient.java index 9cdae161..b489455a 100644 --- a/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/client/VertxTcpClient.java +++ b/jetlinks-components/network-component/tcp-component/src/main/java/org/jetlinks/community/network/tcp/client/VertxTcpClient.java @@ -1,5 +1,7 @@ package org.jetlinks.community.network.tcp.client; +import io.netty.buffer.ByteBuf; +import io.netty.util.ReferenceCountUtil; import io.vertx.core.buffer.Buffer; import io.vertx.core.net.NetClient; import io.vertx.core.net.NetSocket; @@ -77,10 +79,12 @@ public class VertxTcpClient implements TcpClient { sink.error(new SocketException("socket closed")); return; } - Buffer buffer = Buffer.buffer(message.getPayload()); + ByteBuf buf = message.getPayload(); + Buffer buffer = Buffer.buffer(buf); socket.write(buffer, r -> { - keepAlive(); + ReferenceCountUtil.safeRelease(buf); if (r.succeeded()) { + keepAlive(); sink.success(); } else { sink.error(r.cause()); -- Gitee From c67d7b99ce2da3f1498af132b20b91d3179501bd Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 2 Nov 2022 18:13:30 +0800 Subject: [PATCH 11/50] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E9=87=8A=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/mqtt/client/VertxMqttClient.java | 61 +++++++++++-------- .../server/vertx/VertxMqttConnection.java | 30 +++++---- 2 files changed, 53 insertions(+), 38 deletions(-) diff --git a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/client/VertxMqttClient.java b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/client/VertxMqttClient.java index 02c9d21b..fad16676 100644 --- a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/client/VertxMqttClient.java +++ b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/client/VertxMqttClient.java @@ -1,6 +1,8 @@ package org.jetlinks.community.network.mqtt.client; +import io.netty.buffer.ByteBuf; import io.netty.handler.codec.mqtt.MqttQoS; +import io.netty.util.ReferenceCountUtil; import io.vertx.core.buffer.Buffer; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -98,7 +100,11 @@ public class VertxMqttClient implements MqttClient { subscriber .findTopic("/**") .filter(topic -> topic.getSubscribers().size() > 0) - .collectMap(topic -> convertMqttTopic(topic.getSubscribers().iterator().next().getT1()), topic -> topic.getSubscribers().iterator().next().getT3()) + .collectMap(topic -> convertMqttTopic(topic.getSubscribers().iterator().next().getT1()), topic -> topic + .getSubscribers() + .iterator() + .next() + .getT3()) .filter(MapUtils::isNotEmpty) .subscribe(topics -> { log.debug("subscribe mqtt topic {}", topics); @@ -113,13 +119,13 @@ public class VertxMqttClient implements MqttClient { protected String parseTopic(String topic) { //适配emqx共享订阅 if (topic.startsWith("$share")) { - topic= Stream.of(topic.split("/")) - .skip(2) - .collect(Collectors.joining("/", "/", "")); + topic = Stream.of(topic.split("/")) + .skip(2) + .collect(Collectors.joining("/", "/", "")); } else if (topic.startsWith("$queue")) { - topic= topic.substring(6); + topic = topic.substring(6); } - if(topic.startsWith("//")){ + if (topic.startsWith("//")) { return topic.substring(1); } return topic; @@ -172,21 +178,26 @@ public class VertxMqttClient implements MqttClient { private Mono doPublish(MqttMessage message) { return Mono.create((sink) -> { - Buffer buffer = Buffer.buffer(message.getPayload()); + ByteBuf payload = message.getPayload(); + Buffer buffer = Buffer.buffer(payload); client.publish(message.getTopic(), - buffer, - MqttQoS.valueOf(message.getQosLevel()), - message.isDup(), - message.isRetain(), - result -> { - if (result.succeeded()) { - log.info("publish mqtt [{}] message success: {}", client.clientId(), message); - sink.success(); - } else { - log.info("publish mqtt [{}] message error : {}", client.clientId(), message, result.cause()); - sink.error(result.cause()); - } - }); + buffer, + MqttQoS.valueOf(message.getQosLevel()), + message.isDup(), + message.isRetain(), + result -> { + try { + if (result.succeeded()) { + log.info("publish mqtt [{}] message success: {}", client.clientId(), message); + sink.success(); + } else { + log.info("publish mqtt [{}] message error : {}", client.clientId(), message, result.cause()); + sink.error(result.cause()); + } + } finally { + ReferenceCountUtil.safeRelease(payload); + } + }); }); } @@ -194,11 +205,11 @@ public class VertxMqttClient implements MqttClient { public Mono publish(MqttMessage message) { if (loading) { return Mono.create(sink -> - loadSuccessListener - .add(() -> doPublish(message) - .doOnSuccess(sink::success) - .doOnError(sink::error) - .subscribe())); + loadSuccessListener + .add(() -> doPublish(message) + .doOnSuccess(sink::success) + .doOnError(sink::error) + .subscribe())); } return doPublish(message); } diff --git a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttConnection.java b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttConnection.java index e5742530..eb557f14 100644 --- a/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttConnection.java +++ b/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/server/vertx/VertxMqttConnection.java @@ -5,6 +5,7 @@ import io.netty.buffer.Unpooled; import io.netty.handler.codec.DecoderException; import io.netty.handler.codec.mqtt.MqttConnectReturnCode; import io.netty.handler.codec.mqtt.MqttQoS; +import io.netty.util.ReferenceCountUtil; import io.vertx.core.buffer.Buffer; import io.vertx.core.net.SocketAddress; import io.vertx.mqtt.MqttEndpoint; @@ -264,19 +265,22 @@ class VertxMqttConnection implements MqttConnection { ping(); return Mono .create(sink -> { - Buffer buffer = Buffer.buffer(message.getPayload()); - endpoint.publish(message.getTopic(), - buffer, - MqttQoS.valueOf(message.getQosLevel()), - message.isDup(), - message.isRetain(), - result -> { - if (result.succeeded()) { - sink.success(); - } else { - sink.error(result.cause()); - } - } + ByteBuf buf = message.getPayload(); + Buffer buffer = Buffer.buffer(buf); + endpoint.publish( + message.getTopic(), + buffer, + MqttQoS.valueOf(message.getQosLevel()), + message.isDup(), + message.isRetain(), + result -> { + if (result.succeeded()) { + sink.success(); + } else { + sink.error(result.cause()); + } + ReferenceCountUtil.safeRelease(buf); + } ); }); } -- Gitee From 9b2b6d224f0187f9c85c06beedbae2c2ce59b56d Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 7 Nov 2022 10:28:53 +0800 Subject: [PATCH 12/50] getLong --- .../org/jetlinks/community/ValueObject.java | 27 ++++++++++++------- .../message/DeviceMessageMeasurement.java | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/jetlinks-components/common-component/src/main/java/org/jetlinks/community/ValueObject.java b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/ValueObject.java index 8b7734fb..fba27632 100644 --- a/jetlinks-components/common-component/src/main/java/org/jetlinks/community/ValueObject.java +++ b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/ValueObject.java @@ -2,6 +2,7 @@ package org.jetlinks.community; import org.hswebframework.web.bean.FastBeanCopier; import org.jetlinks.community.utils.TimeUtils; +import org.jetlinks.reactor.ql.utils.CastUtils; import org.springframework.util.StringUtils; import java.time.Duration; @@ -15,7 +16,7 @@ public interface ValueObject { default Optional get(String name) { return Optional.ofNullable(values()) - .map(map -> map.get(name)); + .map(map -> map.get(name)); } default Optional getInt(String name) { @@ -44,9 +45,8 @@ public interface ValueObject { .map(Interval::of); } - default Interval getInterval(String name,Interval defaultValue) { - return getString(name) - .map(Interval::of) + default Interval getInterval(String name, Interval defaultValue) { + return getInterval(name) .orElse(defaultValue); } @@ -56,9 +56,14 @@ public interface ValueObject { } default Optional getDate(String name) { - return get(name) - .map(String::valueOf) - .map(TimeUtils::parseDate); + return this + .get(name) + .map(d -> { + if (d instanceof Date) { + return (Date) d; + } + return TimeUtils.parseDate(String.valueOf(d)); + }); } default Date getDate(String name, Date defaultValue) { @@ -83,7 +88,8 @@ public interface ValueObject { } default Optional getBoolean(String name) { - return get(name, Boolean.class); + return get(name) + .map(CastUtils::castBoolean); } default boolean getBoolean(String name, boolean defaultValue) { @@ -95,8 +101,9 @@ public interface ValueObject { .map(obj -> FastBeanCopier.DEFAULT_CONVERT.convert(obj, type, FastBeanCopier.EMPTY_CLASS_ARRAY)); } - static ValueObject of(Map mapVal) { - return () -> mapVal; + @SuppressWarnings("unchecked") + static ValueObject of(Map mapVal) { + return () -> (Map) mapVal; } default T as(Class type) { diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/measurements/message/DeviceMessageMeasurement.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/measurements/message/DeviceMessageMeasurement.java index 9af81953..393ffc4e 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/measurements/message/DeviceMessageMeasurement.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/measurements/message/DeviceMessageMeasurement.java @@ -168,7 +168,7 @@ class DeviceMessageMeasurement extends StaticMeasurement { .to(parameter.getDate("to").orElse(new Date())) .execute(timeSeriesManager.getService(DeviceTimeSeriesMetric.deviceMetrics())::aggregation) .index((index, data) -> SimpleMeasurementValue.of( - data.getInt("count").orElse(0), + data.getLong("count").orElse(0L), data.getString("time").orElse(""), index)) .sort(); -- Gitee From 2c6b85e8af08ca1a9e1460696c9afd128d73b392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8?= Date: Fri, 23 Dec 2022 17:10:36 +0800 Subject: [PATCH 13/50] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 076c59eb..205a6770 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # JetLinks 物联网基础平台 -![GitHub Workflow Status](https://img.shields.io/github/workflow/status/jetlinks/jetlinks-community/Auto%20Deploy%20Docker?label=docker) -![Version](https://img.shields.io/badge/version-1.13--RELEASE-brightgreen) +![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/jetlinks/jetlinks-community/maven.yml?branch=master) +![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) -- Gitee From 203f97afc923693fdc5aee64ea313e8fdb0c7243 Mon Sep 17 00:00:00 2001 From: Zhang Ji <125540670@qq.com> Date: Tue, 10 Jan 2023 11:42:44 +0800 Subject: [PATCH 14/50] =?UTF-8?q?=E5=90=8C=E6=AD=A5README=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E9=93=BE=E6=8E=A5=20(#230)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 205a6770..9150f9b1 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,6 @@ JetLinks 基于Java8,Spring Boot 2.x,WebFlux,Netty,Vert.x,Reactor等开发, ## 文档 -[快速开始](http://doc.jetlinks.cn/basics-guide/quick-start.html) -[开发文档](http://doc.jetlinks.cn/dev-guide/start.html) -[常见问题](http://doc.jetlinks.cn/common-problems/network-components.html) +[快速开始](http://doc.v1.jetlinks.cn/basics-guide/quick-start.html) +[开发文档](http://doc.v1.jetlinks.cn/dev-guide/start.html) +[常见问题](http://doc.v1.jetlinks.cn/common-problems/network-components.html) -- Gitee From 2076a69a56bd9bfccc0ef510f5db0ee3ce33154f Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 10 Feb 2023 13:59:03 +0800 Subject: [PATCH 15/50] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3aa90a6..e8855d16 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # JetLinks 物联网基础平台 -![GitHub Workflow Status](https://img.shields.io/github/workflow/status/jetlinks/jetlinks-community/Auto%20Deploy%20Docker?label=docker) +![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/jetlinks/jetlinks-community/maven.yml?branch=master) ![Version](https://img.shields.io/badge/version-2.0--RELEASE-brightgreen) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/jetlinks/jetlinks-community/maven.yml?branch=master) ![Version](https://img.shields.io/badge/version-1.20--RELEASE-brightgreen) -- Gitee From 6640f1bdf013e8746d4d60e4b942bf9fdbece7af Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 13 Feb 2023 12:01:31 +0800 Subject: [PATCH 16/50] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/maven.yml | 6 +++--- jetlinks-standalone/Dockerfile | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 6915efa9..be5c49ac 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -9,16 +9,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Set up JDK 1.8 uses: actions/setup-java@v1 with: java-version: 1.8 - name: Cache Maven Repository - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~/.m2 - key: jetlinks-community-maven-repository + key: ${{ runner.os }}-${{ hashFiles('**/pom.xml') }} - name: Build with Maven run: ./mvnw clean install -Dmaven.build.timestamp="$(date "+%Y-%m-%d %H:%M:%S")" -Dmaven.test.skip=true -Pbuild && cd jetlinks-standalone && docker build -t registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-standalone:$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) . - name: Login Docker Repo diff --git a/jetlinks-standalone/Dockerfile b/jetlinks-standalone/Dockerfile index a925ffa1..1575f614 100644 --- a/jetlinks-standalone/Dockerfile +++ b/jetlinks-standalone/Dockerfile @@ -10,6 +10,9 @@ COPY --from=builder application/dependencies/ ./ COPY --from=builder application/snapshot-dependencies/ ./ COPY --from=builder application/spring-boot-loader/ ./ COPY --from=builder application/application/ ./ +RUN true COPY docker-entrypoint.sh ./ +RUN true RUN chmod +x docker-entrypoint.sh +RUN true ENTRYPOINT ["./docker-entrypoint.sh"] \ No newline at end of file -- Gitee From 57211334c353942f42a28494071fb7c513d8d2ce Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 13 Feb 2023 12:38:29 +0800 Subject: [PATCH 17/50] RUN true --- jetlinks-standalone/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jetlinks-standalone/Dockerfile b/jetlinks-standalone/Dockerfile index 1575f614..fa293e22 100644 --- a/jetlinks-standalone/Dockerfile +++ b/jetlinks-standalone/Dockerfile @@ -7,8 +7,11 @@ RUN java -Djarmode=layertools -jar application.jar extract FROM openjdk:8u272-jdk WORKDIR application COPY --from=builder application/dependencies/ ./ +RUN true COPY --from=builder application/snapshot-dependencies/ ./ +RUN true COPY --from=builder application/spring-boot-loader/ ./ +RUN true COPY --from=builder application/application/ ./ RUN true COPY docker-entrypoint.sh ./ -- Gitee From 1e58dbb94476fcea9fa49d09ccc2fae10d64b4ef Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Wed, 15 Feb 2023 13:52:10 +0800 Subject: [PATCH 18/50] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=80=8F=E4=BC=A0?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E8=BD=AC=E6=8D=A2=E6=94=AF=E6=8C=81=20(#237)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jetlinks/community/OperationSource.java | 65 ++++ .../org/jetlinks/community/script/Script.java | 4 +- .../community/script/ScriptFactory.java | 2 +- jetlinks-manager/device-manager/pom.xml | 7 + .../entity/TransparentMessageCodecEntity.java | 86 ++++++ .../SimpleTransparentMessageCodec.java | 285 ++++++++++++++++++ .../TransparentDeviceMessageConnector.java | 197 ++++++++++++ .../transparent/TransparentMessageCodec.java | 14 + .../TransparentMessageCodecProvider.java | 13 + .../TransparentMessageCodecProviders.java | 32 ++ ...Jsr223TransparentMessageCodecProvider.java | 86 ++++++ .../TransparentMessageCodecController.java | 159 ++++++++++ .../device/web/protocol/ProtocolDetail.java | 18 +- .../device/web/protocol/TransportDetail.java | 52 +++- .../TransparentMessageCodecRequest.java | 20 ++ .../TransparentMessageDecodeRequest.java | 47 +++ .../TransparentMessageDecodeResponse.java | 40 +++ 17 files changed, 1114 insertions(+), 13 deletions(-) create mode 100644 jetlinks-components/common-component/src/main/java/org/jetlinks/community/OperationSource.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/TransparentMessageCodecEntity.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/SimpleTransparentMessageCodec.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodec.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProvider.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProviders.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/script/Jsr223TransparentMessageCodecProvider.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/TransparentMessageCodecController.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageCodecRequest.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageDecodeRequest.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/response/TransparentMessageDecodeResponse.java diff --git a/jetlinks-components/common-component/src/main/java/org/jetlinks/community/OperationSource.java b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/OperationSource.java new file mode 100644 index 00000000..99c07fe5 --- /dev/null +++ b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/OperationSource.java @@ -0,0 +1,65 @@ +package org.jetlinks.community; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.jetlinks.core.utils.SerializeUtils; +import reactor.util.context.Context; +import reactor.util.context.ContextView; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Optional; + +@AllArgsConstructor(staticName = "of") +@NoArgsConstructor +@Getter +@Setter +public class OperationSource implements Externalizable { + + private static final long serialVersionUID = 1L; + + /** + * ID,type对应操作的唯一标识 + */ + private String id; + + /** + * 操作源名称 + */ + private String name; + + /** + * 操作目标,通常为ID对应的详情数据 + */ + private Object data; + + public static OperationSource of(String id, Object data) { + return of(id, id, data); + } + + public static Context ofContext(String id, String name, Object data) { + return Context.of(OperationSource.class, of(id, name, data)); + } + + public static Optional fromContext(ContextView ctx) { + return ctx.getOrEmpty(OperationSource.class); + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(id); + SerializeUtils.writeObject(name, out); + SerializeUtils.writeObject(data, out); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + id = in.readUTF(); + name = (String) SerializeUtils.readObject(in); + data = SerializeUtils.readObject(in); + } +} diff --git a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/Script.java b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/Script.java index 775c8fad..4a1143c1 100644 --- a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/Script.java +++ b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/Script.java @@ -1,3 +1,5 @@ + + package org.jetlinks.community.script; import lombok.*; @@ -21,4 +23,4 @@ public class Script { return of(name, content, source); } -} +} \ No newline at end of file diff --git a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/ScriptFactory.java b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/ScriptFactory.java index 7f5e312f..a6e4075a 100644 --- a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/ScriptFactory.java +++ b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/ScriptFactory.java @@ -89,4 +89,4 @@ public interface ScriptFactory { T bind(Script script, Class interfaceType); -} +} \ No newline at end of file diff --git a/jetlinks-manager/device-manager/pom.xml b/jetlinks-manager/device-manager/pom.xml index 5e3b64a3..c97d9877 100644 --- a/jetlinks-manager/device-manager/pom.xml +++ b/jetlinks-manager/device-manager/pom.xml @@ -99,6 +99,13 @@ compile + + + org.jetlinks.community + script-component + ${project.version} + compile + diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/TransparentMessageCodecEntity.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/TransparentMessageCodecEntity.java new file mode 100644 index 00000000..f46ecf99 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/TransparentMessageCodecEntity.java @@ -0,0 +1,86 @@ +package org.jetlinks.community.device.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.codec.digest.DigestUtils; +import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType; +import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue; +import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec; +import org.hswebframework.web.api.crud.entity.GenericEntity; +import org.hswebframework.web.api.crud.entity.RecordCreationEntity; +import org.hswebframework.web.api.crud.entity.RecordModifierEntity; +import org.hswebframework.web.crud.annotation.EnableEntityEvent; +import org.hswebframework.web.crud.generator.Generators; +import org.jetlinks.community.device.message.transparent.TransparentMessageCodecProvider; +import org.springframework.util.StringUtils; + +import javax.persistence.Column; +import javax.persistence.Table; +import java.sql.JDBCType; +import java.util.Map; + +@Getter +@Setter +@Table(name = "dev_transparent_codec") +@Schema(description = "透传消息解析器") +@EnableEntityEvent +public class TransparentMessageCodecEntity extends GenericEntity implements RecordCreationEntity, RecordModifierEntity { + + @Schema(description = "产品ID") + @Column(length = 64, nullable = false, updatable = false) + private String productId; + + @Schema(description = "设备ID") + @Column(length = 64, updatable = false) + private String deviceId; + + /** + * @see TransparentMessageCodecProvider#getProvider() + */ + @Schema(description = "编解码器提供商,如: jsr223") + @Column(length = 64, nullable = false) + private String provider; + + /** + * 编解码配置 + * + * @see TransparentMessageCodecProvider#createCodec(Map) + */ + @Schema(description = "编解码配置") + @Column(nullable = false) + @ColumnType(jdbcType = JDBCType.LONGVARCHAR, javaType = String.class) + @JsonCodec + private Map configuration; + + @Schema(description = "创建人ID") + @Column(length = 64, nullable = false, updatable = false) + private String creatorId; + + @Schema(description = "创建时间") + @Column(updatable = false) + @DefaultValue(generator = Generators.CURRENT_TIME) + private Long createTime; + + @Schema(description = "修改人ID") + @Column(length = 64) + private String modifierId; + + @Schema(description = "修改时间") + @DefaultValue(generator = Generators.CURRENT_TIME) + private Long modifyTime; + + @Override + public String getId() { + if (!StringUtils.hasText(super.getId())) { + super.setId( + createId(productId, deviceId) + ); + } + return super.getId(); + } + + public static String createId(String productId, String deviceId) { + return DigestUtils.md5Hex(String.join("|", productId, deviceId)); + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/SimpleTransparentMessageCodec.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/SimpleTransparentMessageCodec.java new file mode 100644 index 00000000..f2238acc --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/SimpleTransparentMessageCodec.java @@ -0,0 +1,285 @@ +package org.jetlinks.community.device.message.transparent; + +import com.alibaba.fastjson.JSON; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import io.netty.util.ReferenceCountUtil; +import lombok.NonNull; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.collections4.MapUtils; +import org.jetlinks.community.OperationSource; +import org.jetlinks.community.PropertyConstants; +import org.jetlinks.core.message.DeviceMessage; +import org.jetlinks.core.message.DirectDeviceMessage; +import org.jetlinks.core.message.MessageType; +import org.jetlinks.core.message.function.ThingFunctionInvokeMessage; +import org.jetlinks.core.message.property.ReadThingPropertyMessage; +import org.jetlinks.core.message.property.ReportPropertyMessage; +import org.jetlinks.core.message.property.WriteThingPropertyMessage; +import org.jetlinks.core.utils.TopicUtils; +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; + +@Slf4j +public class SimpleTransparentMessageCodec implements TransparentMessageCodec { + + @NonNull + protected final Codec codec; + + public SimpleTransparentMessageCodec(@NonNull Codec codec) { + this.codec = codec; + } + + + @Override + public final Mono encode(DeviceMessage message) { + + return Mono.defer(() -> { + + EncodeContext context = new EncodeContext(message); + + codec.encode(context); + + if (context.payload != null) { + DirectDeviceMessage msg = new DirectDeviceMessage(); + msg.setPayload(ByteBufUtil.getBytes(context.payload)); + //release + ReferenceCountUtil.safeRelease(context.payload); + + msg.setMessageId(message.getMessageId()); + msg.setDeviceId(message.getDeviceId()); + if (null != message.getHeaders()) { + message.getHeaders().forEach(msg::addHeader); + } + context.headers.forEach(msg::addHeader); + return Mono.just(msg); + + } + return Mono.empty(); + }); + } + + @Override + public Flux decode(DirectDeviceMessage message) { + + return Mono + .fromCallable(() -> codec.decode(new DecodeContext(message))) + .flatMapMany(this::convert) + .doOnNext(msg -> { + String from = message.getMessageId(); + if (from == null) { + from = message.getHeader(PropertyConstants.uid).orElse(null); + } + if (from != null) { + msg.addHeader("decodeFrom", from); + } + msg.thingId(message.getThingType(), message.getThingId()); + }); + + } + + @SuppressWarnings("all") + protected Flux convert(Object msg) { + if (msg == null) { + return Flux.empty(); + } + if (msg instanceof DeviceMessage) { + return Flux.just(((DeviceMessage) msg)); + } + if (msg instanceof Map) { + if (MapUtils.isEmpty(((Map) msg))) { + return Flux.empty(); + } + MessageType type = MessageType.of(((Map) msg)).orElse(MessageType.UNKNOWN); + if (type == MessageType.UNKNOWN) { + //返回map但是未设备未设备消息,则转为属性上报 + return Flux.just(new ReportPropertyMessage().properties(((Map) msg))); + } + return Mono + .justOrEmpty(type.convert(((Map) msg))) + .flux() + .cast(DeviceMessage.class); + } + if (msg instanceof Collection) { + return Flux + .fromIterable(((Collection) msg)) + .flatMap(this::convert); + } + if (msg instanceof Publisher) { + return Flux + .from(((Publisher) msg)) + .flatMap(this::convert); + } + return Flux.error(new UnsupportedOperationException("unsupported data:" + msg)); + } + + public static class DecodeContext { + final DirectDeviceMessage msg; + final ByteBuf buffer; + + DecodeContext(DirectDeviceMessage msg) { + this.msg = msg; + this.buffer = msg.asByteBuf(); + } + + public long timestamp() { + return msg.getTimestamp(); + } + + public ByteBuf payload() { + return buffer; + } + + public Object json() { + return JSON.parse(buffer.array()); + } + + public Map pathVars(String pattern, String path) { + return TopicUtils.getPathVariables(pattern, path); + } + + public String url() { + return msg.getHeader("url") + .map(String::valueOf) + .orElse(null); + } + + public String topic() { + return msg.getHeader("topic") + .map(String::valueOf) + .orElse(null); + } + + public DirectDeviceMessage message() { + return msg; + } + + } + + /** + *
{@code
+     *
+     * context
+     * .whenReadProperty("temp",()->return "0x0122")
+     * .whenFunction("func",args->{
+     *
+     * })
+     *
+     * }
+ */ + public static class EncodeContext { + + private final DeviceMessage source; + private ByteBuf payload; + private final Map headers = new HashMap<>(); + + public EncodeContext(DeviceMessage source) { + this.source = source; + } + + public DeviceMessage message() { + return source; + } + + public EncodeContext topic(String topic) { + headers.put("topic", topic); + return this; + } + + public ByteBuf payload() { + return payload == null ? payload = Unpooled.buffer() : payload; + } + + public ByteBuf newBuffer() { + return Unpooled.buffer(); + } + + @SneakyThrows + public EncodeContext setPayload(String strOrHex, String charset) { + if (strOrHex.startsWith("0x")) { + payload().writeBytes(Hex.decodeHex(strOrHex.substring(2))); + } else { + payload().writeBytes(strOrHex.getBytes(charset)); + } + return this; + } + + @SneakyThrows + public EncodeContext setPayload(String strOrHex) { + setPayload(strOrHex, "utf-8"); + return this; + } + + public EncodeContext setPayload(Object data) { + + if (data instanceof String) { + setPayload(((String) data)); + } + + if (data instanceof byte[]) { + payload().writeBytes(((byte[]) data)); + } + + if (data instanceof ByteBuf) { + this.payload = ((ByteBuf) data); + } + //todo 更多类型? + + return this; + } + + public EncodeContext whenFunction(String functionId, Function supplier) { + if (source instanceof ThingFunctionInvokeMessage) { + ThingFunctionInvokeMessage msg = ((ThingFunctionInvokeMessage) source); + if ("*".equals(msg.getFunctionId()) || Objects.equals(functionId, msg.getFunctionId())) { + setPayload(supplier.apply(msg.inputsToMap())); + } + } + return this; + } + + public EncodeContext whenWriteProperty(String property, Function supplier) { + if (source instanceof WriteThingPropertyMessage) { + if ("*".equals(property)) { + setPayload(supplier.apply(((WriteThingPropertyMessage) source).getProperties())); + return this; + } + Object value = ((WriteThingPropertyMessage) source).getProperties().get(property); + if (value != null) { + setPayload(supplier.apply(value)); + } + } + return this; + } + + public EncodeContext whenReadProperties(Function, Object> supplier) { + if (source instanceof ReadThingPropertyMessage) { + setPayload(supplier.apply(((ReadThingPropertyMessage) source).getProperties())); + } + return this; + } + + public EncodeContext whenReadProperty(String property, Supplier supplier) { + if (source instanceof ReadThingPropertyMessage) { + if ("*".equals(property) || ((ReadThingPropertyMessage) source).getProperties().contains(property)) { + setPayload(supplier.get()); + } + } + return this; + } + } + + public interface Codec { + Object decode(DecodeContext context); + + Object encode(EncodeContext context); + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java new file mode 100644 index 00000000..22f6e27e --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java @@ -0,0 +1,197 @@ +package org.jetlinks.community.device.message.transparent; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; +import org.hswebframework.web.crud.events.EntityCreatedEvent; +import org.hswebframework.web.crud.events.EntityDeletedEvent; +import org.hswebframework.web.crud.events.EntityModifyEvent; +import org.hswebframework.web.crud.events.EntitySavedEvent; +import org.hswebframework.web.exception.ValidationException; +import org.jctools.maps.NonBlockingHashMap; +import org.jetlinks.core.device.DeviceConfigKey; +import org.jetlinks.core.device.DeviceOperator; +import org.jetlinks.core.event.EventBus; +import org.jetlinks.core.event.Subscription; +import org.jetlinks.core.message.DeviceMessage; +import org.jetlinks.core.message.DirectDeviceMessage; +import org.jetlinks.core.message.Headers; +import org.jetlinks.core.message.interceptor.DeviceMessageSenderInterceptor; +import org.jetlinks.community.OperationSource; +import org.jetlinks.community.device.entity.TransparentMessageCodecEntity; +import org.jetlinks.community.gateway.annotation.Subscribe; +import org.jetlinks.supports.server.DecodedClientMessageHandler; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.Map; + +@Slf4j +@Component +public class TransparentDeviceMessageConnector implements CommandLineRunner, DeviceMessageSenderInterceptor { + + private final ReactiveRepository repository; + + private final DecodedClientMessageHandler messageHandler; + + private final EventBus eventBus; + + private final Map codecs = new NonBlockingHashMap<>(); + + public TransparentDeviceMessageConnector(@SuppressWarnings("all") + ReactiveRepository repository, + DecodedClientMessageHandler messageHandler, + EventBus eventBus, + ObjectProvider providers) { + this.repository = repository; + this.messageHandler = messageHandler; + this.eventBus = eventBus; + for (TransparentMessageCodecProvider provider : providers) { + TransparentMessageCodecProviders.addProvider(provider); + } + } + + + @Subscribe("/device/*/*/message/direct") + public Mono handleMessage(DirectDeviceMessage message) { + String productId = message.getHeaderOrDefault(Headers.productId); + String deviceId = message.getDeviceId(); + TransparentMessageCodec codec = getCodecOrNull(productId, deviceId); + if (null == codec) { + return Mono.empty(); + } + return codec + .decode(message) + .flatMap(msg -> messageHandler.handleMessage(null, msg)) + .then(); + } + + private TransparentMessageCodec getCodecOrNull(String productId, String deviceId) { + CacheKey cacheKey = new CacheKey(productId, deviceId); + TransparentMessageCodec codec = codecs.get(cacheKey); + if (codec == null) { + cacheKey.setDeviceId(null); + codec = codecs.get(cacheKey); + } + return codec; + } + + @Override + public Mono preSend(DeviceOperator device, DeviceMessage message) { + return device + .getSelfConfig(DeviceConfigKey.productId) + .mapNotNull(productId -> getCodecOrNull(productId, device.getDeviceId())) + .flatMap(codec -> codec + .encode(message) + .doOnNext(msg -> { + msg.addHeader("encodeBy", message.getMessageType().name()); + //所有透传消息都设置为异步 + msg.addHeader(Headers.async, true); + // msg.addHeader(Headers.sendAndForget, true); + }) + ) + .defaultIfEmpty(message); + } + + + @Subscribe(value = "/_sys/transparent-codec/load", features = Subscription.Feature.broker) + public Mono doLoadCodec(TransparentMessageCodecEntity entity) { + CacheKey key = new CacheKey(entity.getProductId(), entity.getDeviceId()); + TransparentMessageCodecProvider provider = TransparentMessageCodecProviders + .getProvider(entity.getProvider()) + .orElseThrow(() -> new ValidationException("codec", "error.unsupported_codec", entity.getProvider())); + return provider + .createCodec(entity.getConfiguration()) + .doOnNext(codec -> codecs.put(key, codec)) + .contextWrite(OperationSource.ofContext(entity.getId(),null,entity)) + .switchIfEmpty(Mono.fromRunnable(() -> codecs.remove(key))) + .then(); + } + + @Subscribe(value = "/_sys/transparent-codec/removed", features = Subscription.Feature.broker) + public Mono doRemoveCodec(TransparentMessageCodecEntity entity) { + CacheKey key = new CacheKey(entity.getProductId(), entity.getDeviceId()); + codecs.remove(key); + return Mono.empty(); + } + + @EventListener + public void handleEntityEvent(EntityCreatedEvent event) { + event.async( + Flux.fromIterable(event.getEntity()) + .flatMap(this::loadCodec) + ); + } + + @EventListener + public void handleEntityEvent(EntitySavedEvent event) { + event.async( + Flux.fromIterable(event.getEntity()) + .flatMap(this::loadCodec) + ); + } + + @EventListener + public void handleEntityEvent(EntityModifyEvent event) { + event.async( + Flux.fromIterable(event.getAfter()) + .flatMap(this::loadCodec) + ); + } + + @EventListener + public void handleEntityEvent(EntityDeletedEvent event) { + event.async( + Flux.fromIterable(event.getEntity()) + .flatMap(this::removeCodec) + ); + } + + public Mono loadCodec(TransparentMessageCodecEntity entity) { + return doLoadCodec(entity) + .then( + eventBus + .publish("/_sys/transparent-codec/load", entity) + .then() + ); + } + + public Mono removeCodec(TransparentMessageCodecEntity entity) { + return doRemoveCodec(entity) + .then( + eventBus + .publish("/_sys/transparent-codec/removed", entity) + .then() + ); + } + + @Override + public void run(String... args) throws Exception { + repository + .createQuery() + .fetch() + .flatMap(e -> this + .doLoadCodec(e) + .onErrorResume(err -> { + log.error("load transparent device message codec [{}:{}] error", e.getId(), e.getProvider(), err); + return Mono.empty(); + })) + .subscribe(); + } + + @Getter + @Setter + @EqualsAndHashCode + @AllArgsConstructor + static class CacheKey { + private String productId; + private String deviceId; + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodec.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodec.java new file mode 100644 index 00000000..7c7e043a --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodec.java @@ -0,0 +1,14 @@ +package org.jetlinks.community.device.message.transparent; + +import org.jetlinks.core.message.DeviceMessage; +import org.jetlinks.core.message.DirectDeviceMessage; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface TransparentMessageCodec { + + Flux decode(DirectDeviceMessage message); + + Mono encode(DeviceMessage message); + +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProvider.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProvider.java new file mode 100644 index 00000000..00a81a9f --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProvider.java @@ -0,0 +1,13 @@ +package org.jetlinks.community.device.message.transparent; + +import reactor.core.publisher.Mono; + +import java.util.Map; + +public interface TransparentMessageCodecProvider { + + String getProvider(); + + Mono createCodec(Map configuration); + +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProviders.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProviders.java new file mode 100644 index 00000000..35305172 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentMessageCodecProviders.java @@ -0,0 +1,32 @@ +package org.jetlinks.community.device.message.transparent; + +import org.hswebframework.web.exception.I18nSupportException; +import org.jctools.maps.NonBlockingHashMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class TransparentMessageCodecProviders { + + public static Map providers = new NonBlockingHashMap<>(); + + + static void addProvider(TransparentMessageCodecProvider provider) { + providers.put(provider.getProvider(), provider); + } + + public static List getProviders() { + return new ArrayList<>(providers.values()); + } + + public static Optional getProvider(String provider) { + return Optional.ofNullable(providers.get(provider)); + } + + public static TransparentMessageCodecProvider getProviderNow(String provider) { + return getProvider(provider) + .orElseThrow(()->new I18nSupportException("error.unsupported_codec",provider)); + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/script/Jsr223TransparentMessageCodecProvider.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/script/Jsr223TransparentMessageCodecProvider.java new file mode 100644 index 00000000..f7928e7d --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/script/Jsr223TransparentMessageCodecProvider.java @@ -0,0 +1,86 @@ +package org.jetlinks.community.device.message.transparent.script; + +import org.hswebframework.web.exception.ValidationException; +import org.jetlinks.community.device.message.transparent.SimpleTransparentMessageCodec; +import org.jetlinks.community.device.message.transparent.TransparentMessageCodec; +import org.jetlinks.community.device.message.transparent.TransparentMessageCodecProvider; +import org.jetlinks.community.script.Script; +import org.jetlinks.community.script.Scripts; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; +import reactor.core.publisher.Mono; + +import java.util.Map; +import java.util.function.Function; + +@Component +public class Jsr223TransparentMessageCodecProvider implements TransparentMessageCodecProvider { + + @Override + public String getProvider() { + return "jsr223"; + } + + @Override + public Mono createCodec(Map configuration) { + String lang = (String) configuration.getOrDefault("lang", "js"); + String script = (String) configuration.get("script"); + Assert.hasText(lang, "lang can not be null"); + Assert.hasText(script, "script can not be null"); + + CodecContext context = new CodecContext(); + + SimpleTransparentMessageCodec.Codec codec = Scripts + .getFactory(lang) + .bind(Script.of("jsr223-transparent", script), + SimpleTransparentMessageCodec.Codec.class); + + if (context.encoder == null && codec != null) { + context.onDownstream(codec::encode); + } + if (context.decoder == null && codec != null) { + context.onUpstream(codec::decode); + } + + if (codec == null && context.encoder == null && context.decoder == null) { + return Mono.error(new ValidationException("script", "error.codec_message_undefined")); + } + return Mono + .deferContextual(ctx -> Mono + .just( + new SimpleTransparentMessageCodec(context) + )); + } + + public static class CodecContext implements SimpleTransparentMessageCodec.Codec { + + private Function encoder; + private Function decoder; + + public void onDownstream(Function encoder) { + this.encoder = encoder; + } + + public void onUpstream(Function decoder) { + this.decoder = decoder; + } + + @Override + public Object decode(SimpleTransparentMessageCodec.DecodeContext context) { + if (decoder == null) { + return null; + } + return decoder.apply(context); + } + + @Override + public Object encode(SimpleTransparentMessageCodec.EncodeContext context) { + if (encoder == null) { + return null; + } + return encoder.apply(context); + } + + } + +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/TransparentMessageCodecController.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/TransparentMessageCodecController.java new file mode 100644 index 00000000..a2f2e8cb --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/TransparentMessageCodecController.java @@ -0,0 +1,159 @@ +package org.jetlinks.community.device.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; +import org.hswebframework.web.authorization.annotation.QueryAction; +import org.hswebframework.web.authorization.annotation.Resource; +import org.hswebframework.web.authorization.annotation.SaveAction; +import org.hswebframework.web.i18n.LocaleUtils; +import org.jetlinks.community.device.entity.TransparentMessageCodecEntity; +import org.jetlinks.community.device.message.transparent.TransparentMessageCodecProviders; +import org.jetlinks.community.device.web.request.TransparentMessageCodecRequest; +import org.jetlinks.community.device.web.request.TransparentMessageDecodeRequest; +import org.jetlinks.community.device.web.response.TransparentMessageDecodeResponse; +import org.jetlinks.core.device.DeviceOperator; +import org.jetlinks.core.device.DeviceProductOperator; +import org.jetlinks.core.device.DeviceRegistry; +import org.jetlinks.core.metadata.DeviceMetadata; +import org.jetlinks.core.utils.TypeScriptUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/device/transparent-codec") +@Tag(name = "设备透传消息解析配置") +@AllArgsConstructor +@Resource(id = "transparent-codec", name = "设备透传消息解析配置") +public class TransparentMessageCodecController { + + private final ReactiveRepository repository; + + private final DeviceRegistry registry; + + + @PostMapping("/decode-test") + @QueryAction + @Operation(summary = "测试解码") + public Mono getCodec(@RequestBody Mono requestMono) { + return requestMono + .flatMapMany(req -> TransparentMessageCodecProviders + .getProviderNow(req.getProvider()) + .createCodec(req.getConfiguration()) + .flatMapMany(codec -> codec.decode(req.toMessage()))) + .collectList() + .map(TransparentMessageDecodeResponse::of) + .onErrorResume(err -> LocaleUtils.doWithReactive( + err, + Throwable::getLocalizedMessage, + (e, msg) -> TransparentMessageDecodeResponse.error(msg))); + } + + @GetMapping("/{productId}/{deviceId}.d.ts") + @QueryAction + @Operation(summary = "获取设备的TypeScript定义信息") + public Mono getTypescriptDeclares(@PathVariable String productId, + @PathVariable String deviceId) { + return registry + .getDevice(deviceId) + .flatMap(DeviceOperator::getMetadata) + .flatMap(this::getTypescriptDeclares); + } + + @GetMapping("/{productId}.d.ts") + @QueryAction + @Operation(summary = "获取产品的TypeScript定义信息") + public Mono getTypescriptDeclares(@PathVariable String productId) { + return registry + .getProduct(productId) + .flatMap(DeviceProductOperator::getMetadata) + .flatMap(this::getTypescriptDeclares); + } + + + @GetMapping("/{productId}/{deviceId}") + @QueryAction + @Operation(summary = "获取设备的解析规则") + public Mono getCodec(@PathVariable String productId, + @PathVariable String deviceId) { + + + return repository + .findById(TransparentMessageCodecEntity.createId(productId, deviceId)) + //设备没有则获取产品的 + .switchIfEmpty(Mono.defer(() -> { + if (StringUtils.hasText(deviceId)) { + return repository.findById(TransparentMessageCodecEntity.createId(productId, null)); + } + return Mono.empty(); + })); + } + + @GetMapping("/{productId}") + @QueryAction + @Operation(summary = "获取产品的解析规则") + public Mono getCodec(@PathVariable String productId) { + + return getCodec(productId, null); + } + + + @PostMapping("/{productId}/{deviceId}") + @SaveAction + @Operation(summary = "保存设备解析规则") + public Mono saveCodec(@PathVariable String productId, + @PathVariable String deviceId, + @RequestBody Mono requestMono) { + + + return requestMono + .flatMap(request-> { + TransparentMessageCodecEntity codec = new TransparentMessageCodecEntity(); + codec.setProductId(productId); + codec.setDeviceId(deviceId); + codec.setProvider(request.getProvider()); + codec.setConfiguration(request.getConfiguration()); + return repository.save(codec); + }) + .then(); + } + + @PostMapping("/{productId}") + @Operation(summary = "保存产品解析规则") + public Mono saveCodec(@PathVariable String productId, + @RequestBody Mono requestMono) { + return saveCodec(productId, null, requestMono); + } + + @DeleteMapping("/{productId}/{deviceId}") + @SaveAction + @Operation(summary = "重置设备的解析规则") + public Mono removeCodec(@PathVariable String productId, + @PathVariable String deviceId) { + + + return repository + .deleteById(TransparentMessageCodecEntity.createId(productId, deviceId)) + .then(); + } + + @DeleteMapping("/{productId}") + @SaveAction + @Operation(summary = "重置产品的解析规则") + public Mono removeCodec(@PathVariable String productId) { + return removeCodec(productId, null); + } + + + private Mono getTypescriptDeclares(DeviceMetadata metadata) { + StringBuilder builder = new StringBuilder(); + + TypeScriptUtils.createMetadataDeclare(metadata, builder); + TypeScriptUtils.loadDeclare("transparent-codec", builder); + + return Mono.just(builder.toString()); + } + +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/ProtocolDetail.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/ProtocolDetail.java index cd047caf..e0153d88 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/ProtocolDetail.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/ProtocolDetail.java @@ -1,8 +1,7 @@ package org.jetlinks.community.device.web.protocol; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; import org.jetlinks.core.ProtocolSupport; import reactor.core.publisher.Mono; @@ -11,22 +10,27 @@ import java.util.List; @Getter @Setter @AllArgsConstructor +@Generated +@NoArgsConstructor public class ProtocolDetail { + @Schema(description = "协议ID") private String id; + @Schema(description = "协议名称") private String name; + @Schema(description = "协议说明") + private String description; + private List transports; public static Mono of(ProtocolSupport support) { + return support .getSupportedTransport() .flatMap(trans -> TransportDetail.of(support, trans)) .collectList() - .map(details -> new ProtocolDetail(support.getId(), support.getName(), details)); + .map(details -> new ProtocolDetail(support.getId(), support.getName(),support.getDescription(), details)); } } - - - diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/TransportDetail.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/TransportDetail.java index 5d4019a7..362f15fb 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/TransportDetail.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/protocol/TransportDetail.java @@ -1,22 +1,66 @@ package org.jetlinks.community.device.web.protocol; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import org.jetlinks.community.protocol.ProtocolFeature; import org.jetlinks.core.ProtocolSupport; import org.jetlinks.core.message.codec.Transport; +import org.jetlinks.core.route.Route; +import org.jetlinks.supports.official.JetLinksDeviceMetadataCodec; import reactor.core.publisher.Mono; +import java.util.List; + @Getter @Setter @AllArgsConstructor +@NoArgsConstructor +@Generated public class TransportDetail { + @Schema(description = "ID") private String id; + @Schema(description = "名称") private String name; + @Schema(description = "其他设置") + private List features; + + @Schema(description = "路由信息") + private List routes; + + @Schema(description = "文档信息") + private String document; + + @Schema(description = "默认物模型") + private String metadata; + public static Mono of(ProtocolSupport support, Transport transport) { - return Mono.just(new TransportDetail(transport.getId(), transport.getName())); + return Mono + .zip( + support + //T1: 路由信息 + .getRoutes(transport) + .collectList(), + support + //T2: 协议特性 + .getFeatures(transport) + .map(ProtocolFeature::of) + .collectList(), + support + //T3: 默认物模型 + .getDefaultMetadata(transport) + .flatMap(JetLinksDeviceMetadataCodec.getInstance()::encode) + .defaultIfEmpty("") + ) + .map(tp3 -> new TransportDetail( + transport.getId(), + transport.getName(), + tp3.getT2(), + tp3.getT1(), + support.getDocument(transport), + tp3.getT3())); + } } \ No newline at end of file diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageCodecRequest.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageCodecRequest.java new file mode 100644 index 00000000..b421929d --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageCodecRequest.java @@ -0,0 +1,20 @@ +package org.jetlinks.community.device.web.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; +import java.util.Map; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class TransparentMessageCodecRequest { + @NotBlank + private String provider; + + private Map configuration; +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageDecodeRequest.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageDecodeRequest.java new file mode 100644 index 00000000..8fb15215 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/request/TransparentMessageDecodeRequest.java @@ -0,0 +1,47 @@ +package org.jetlinks.community.device.web.request; + +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.collections4.MapUtils; +import org.hswebframework.web.validator.ValidatorUtils; +import org.jetlinks.core.message.DirectDeviceMessage; + +import javax.validation.constraints.NotBlank; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +@Getter +@Setter +public class TransparentMessageDecodeRequest extends TransparentMessageCodecRequest { + + // headers:{ + // "topic":"/xxxx", + // "url":"/xxx" + // } + private Map headers; + + @NotBlank + private String payload; + + @SneakyThrows + public DirectDeviceMessage toMessage() { + ValidatorUtils.tryValidate(this); + + DirectDeviceMessage message = new DirectDeviceMessage(); + message.setDeviceId("test"); + if (MapUtils.isNotEmpty(headers)) { + headers.forEach(message::addHeader); + } + byte[] data; + if (payload.startsWith("0x")) { + data = Hex.decodeHex(payload.substring(2)); + } else { + data = payload.getBytes(StandardCharsets.UTF_8); + } + message.setPayload(data); + + return message; + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/response/TransparentMessageDecodeResponse.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/response/TransparentMessageDecodeResponse.java new file mode 100644 index 00000000..a781a352 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/response/TransparentMessageDecodeResponse.java @@ -0,0 +1,40 @@ +package org.jetlinks.community.device.web.response; + +import lombok.Getter; +import lombok.Setter; +import org.jetlinks.core.message.DeviceMessage; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Setter +public class TransparentMessageDecodeResponse { + private boolean success; + + private String reason; + + private List outputs; + + public static TransparentMessageDecodeResponse of(List messages) { + TransparentMessageDecodeResponse response = new TransparentMessageDecodeResponse(); + response.success = true; + response.outputs = messages + .stream() + .map(DeviceMessage::toJson) + .collect(Collectors.toList()); + + return response; + } + + public static TransparentMessageDecodeResponse error(String reason) { + TransparentMessageDecodeResponse response = new TransparentMessageDecodeResponse(); + response.success = false; + response.reason = reason; + return response; + } + + public static TransparentMessageDecodeResponse of(Throwable err) { + return error(err.getLocalizedMessage()); + } +} -- Gitee From d2262e278ae8d1a87c0a4e3653f82340c93e426d Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Mon, 27 Feb 2023 15:08:40 +0800 Subject: [PATCH 19/50] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E7=BC=BA=E5=A4=B1)?= =?UTF-8?q?:=20=E6=B7=BB=E5=8A=A0=E8=8F=9C=E5=8D=95=E5=92=8C=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=95=B0=E6=8D=AE=E9=AA=8C=E8=AF=81=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=20(#245)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/auth/web/MenuController.java | 28 ++++++++++ .../auth/web/PermissionController.java | 56 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/PermissionController.java diff --git a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/MenuController.java b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/MenuController.java index 871bb85c..b258ee80 100755 --- a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/MenuController.java +++ b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/MenuController.java @@ -15,8 +15,10 @@ import org.hswebframework.web.authorization.annotation.*; import org.hswebframework.web.authorization.exception.UnAuthorizedException; import org.hswebframework.web.crud.service.ReactiveCrudService; import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController; +import org.hswebframework.web.exception.ValidationException; import org.hswebframework.web.i18n.LocaleUtils; import org.hswebframework.web.system.authorization.defaults.service.DefaultPermissionService; +import org.hswebframework.web.validator.CreateGroup; import org.jetlinks.community.auth.configuration.MenuProperties; import org.jetlinks.community.auth.entity.MenuEntity; import org.jetlinks.community.auth.entity.MenuView; @@ -24,6 +26,7 @@ import org.jetlinks.community.auth.service.DefaultMenuService; import org.jetlinks.community.auth.service.MenuGrantService; import org.jetlinks.community.auth.service.request.MenuGrantRequest; import org.jetlinks.community.auth.web.request.AuthorizationSettingDetail; +import org.jetlinks.community.web.response.ValidationResult; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; @@ -263,6 +266,31 @@ public class MenuController implements ReactiveServiceCrudController codeValidate(@RequestParam @Parameter(description = "菜单编码") String code, + @RequestParam(required = false) + @Parameter(description = "外部菜单所属应用ID") String appId, + @RequestParam @Parameter(description = "菜单所有者") String owner) { + return LocaleUtils.currentReactive() + .flatMap(locale -> { + MenuEntity entity = new MenuEntity(); + entity.setCode(code); + entity.setOwner(owner); + entity.tryValidate("code", CreateGroup.class); + + return defaultMenuService + .findById(entity.getId()) + .map(menu -> ValidationResult + .error(LocaleUtils.resolveMessage("error.id_already_exists", locale))); + }) + .defaultIfEmpty(ValidationResult.success()) + .onErrorResume(ValidationException.class, e -> Mono.just(e.getI18nCode()) + .map(ValidationResult::error)); + } + private Mono getAuthorizationSettingDetail(Flux menus) { return Mono .zip(menus diff --git a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/PermissionController.java b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/PermissionController.java new file mode 100644 index 00000000..2a75c76e --- /dev/null +++ b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/PermissionController.java @@ -0,0 +1,56 @@ +package org.jetlinks.community.auth.web; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.hswebframework.web.authorization.annotation.Authorize; +import org.hswebframework.web.authorization.annotation.QueryAction; +import org.hswebframework.web.authorization.annotation.Resource; +import org.hswebframework.web.exception.ValidationException; +import org.hswebframework.web.i18n.LocaleUtils; +import org.hswebframework.web.system.authorization.api.entity.PermissionEntity; +import org.hswebframework.web.system.authorization.defaults.service.DefaultPermissionService; +import org.hswebframework.web.validator.CreateGroup; +import org.jetlinks.community.web.response.ValidationResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +/** + * 权限管理. + * + * @author zhangji 2022/12/23 + */ +@RestController +@RequestMapping("/permission") +@Authorize +@Resource(id = "permission", name = "权限管理", group = "system") +@Tag(name = "权限管理") +@AllArgsConstructor +public class PermissionController { + + private final DefaultPermissionService permissionService; + + @GetMapping("/id/_validate") + @QueryAction + @Operation(summary = "验证权限ID是否合法") + public Mono permissionIdValidate2(@RequestParam @Parameter(description = "权限ID") String id) { + return LocaleUtils.currentReactive() + .flatMap(locale -> { + PermissionEntity entity = new PermissionEntity(); + entity.setId(id); + entity.tryValidate("id", CreateGroup.class); + + return permissionService + .findById(id) + .map(permission -> ValidationResult + .error(LocaleUtils.resolveMessage("error.id_already_exists", locale))); + }) + .defaultIfEmpty(ValidationResult.success()) + .onErrorResume(ValidationException.class, e -> Mono.just(e.getI18nCode()) + .map(ValidationResult::error)); + } +} -- Gitee From 0efeff2dd7d7489c6e570d7c674b6b61df36e860 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 28 Feb 2023 15:55:16 +0800 Subject: [PATCH 20/50] feat(repo): add build profile --- pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pom.xml b/pom.xml index 82c3a294..df0b0263 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,19 @@ + + + build + + + maven-central + central + https://repo1.maven.org/maven2/ + + + + + ${project.artifactId} -- Gitee From 6a186d6eba654d1f61bc8a32c7903750e901490b Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 2 Mar 2023 09:46:07 +0800 Subject: [PATCH 21/50] =?UTF-8?q?feat(=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86?= =?UTF-8?q?):=20=E4=BC=98=E5=8C=96=E8=AE=BE=E5=A4=87=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E7=9A=84=E6=A0=87=E7=AD=BE=E6=8E=92=E5=BA=8F=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device/response/DeviceDetail.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java index b2c3378b..341aa271 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java @@ -16,10 +16,7 @@ import org.jetlinks.core.Values; import org.jetlinks.core.device.DeviceConfigKey; import org.jetlinks.core.device.DeviceOperator; import org.jetlinks.core.device.DeviceProductOperator; -import org.jetlinks.core.metadata.ConfigPropertyMetadata; -import org.jetlinks.core.metadata.DeviceMetadata; -import org.jetlinks.core.metadata.Feature; -import org.jetlinks.core.metadata.SimpleFeature; +import org.jetlinks.core.metadata.*; import org.jetlinks.supports.official.JetLinksDeviceMetadataCodec; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -230,7 +227,19 @@ public class DeviceDetail { (_1, _2) -> StringUtils.hasText(_1.getValue()) ? _1 : _2)); this.tags = new ArrayList<>(map.values()); - this.tags.sort(Comparator.comparing(DeviceTagEntity::getCreateTime)); + + DeviceMetadata deviceMetadata = decodeMetadata(); + if (null != deviceMetadata) { + this.tags.sort(Comparator + .comparingLong(tag -> { + PropertyMetadata tagMetadata = deviceMetadata.getTagOrNull(tag.getKey()); + return tagMetadata == null + ? tag.getCreateTime().getTime() + : deviceMetadata.getTags().indexOf(tagMetadata); + })); + } else { + this.tags.sort(Comparator.comparing(DeviceTagEntity::getCreateTime)); + } if (StringUtils.hasText(id)) { for (DeviceTagEntity tag : getTags()) { -- Gitee From a6503b49e96f32e9930daf17051f372fe3957e11 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 6 Mar 2023 17:40:10 +0800 Subject: [PATCH 22/50] =?UTF-8?q?feat(TDEngine):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86,=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=97=B6=E6=89=BE=E4=B8=8D=E5=88=B0=E8=A1=A8=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E6=8A=9B=E5=87=BA=E9=94=99=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jetlinks/community/tdengine/TDEngineUtils.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java b/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java index 4f1ca573..34ef572e 100644 --- a/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java +++ b/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java @@ -35,7 +35,10 @@ public class TDEngineUtils { public static void checkExecuteResult(String sql, JSONObject result) { if (result.getInteger("code") != 0) { String error = result.getString("desc"); - if (sql != null && sql.startsWith("describe") && error.contains("does not exist")) { + if (sql != null && (sql.startsWith("describe") + || sql.startsWith("select") + || sql.startsWith("SELECT")) + && error.contains("does not exist")) { return; } if (sql != null) { -- Gitee From 3fc1b11e29f282b515bc6a54dadf78e0c5395e0e Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 8 Mar 2023 14:20:45 +0800 Subject: [PATCH 23/50] =?UTF-8?q?fix(=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86)?= =?UTF-8?q?:=20=E4=BF=AE=E5=A4=8D=E6=B3=A8=E9=94=80=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E5=90=8E=E8=AE=BE=E5=A4=87=E4=B8=AD=E5=BF=83=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=9C=AA=E6=B8=85=E7=90=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/device/service/LocalDeviceProductService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceProductService.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceProductService.java index 51285ec0..fbd25f2b 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceProductService.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceProductService.java @@ -63,7 +63,11 @@ public class LocalDeviceProductService extends GenericReactiveCrudService + registry + .unregisterProduct(id) + .thenReturn(integer)); } -- Gitee From d0208967f07df912be5373ac96862f06395368ba Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 9 Mar 2023 11:12:04 +0800 Subject: [PATCH 24/50] =?UTF-8?q?fix(=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86)?= =?UTF-8?q?:=20=E5=AF=BC=E5=85=A5=E8=AE=BE=E5=A4=87=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=BF=BD=E7=95=A5=E7=A9=BA=E5=AD=97=E7=AC=A6=E4=B8=B2=E7=9A=84?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jetlinks/community/device/web/excel/DeviceExcelInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/excel/DeviceExcelInfo.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/excel/DeviceExcelInfo.java index ff6ff5e4..fb457581 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/excel/DeviceExcelInfo.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/excel/DeviceExcelInfo.java @@ -38,7 +38,7 @@ public class DeviceExcelInfo { private String state; public void config(String key, Object value) { - if (value == null) { + if (value == null || value instanceof String && !StringUtils.hasText((String) value)) { return; } configuration.put(key, value); -- Gitee From 552dfd550b652f5c1d8250a48a91c1d3a1cc5d0d Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 14 Mar 2023 16:51:09 +0800 Subject: [PATCH 25/50] =?UTF-8?q?fix(=E5=9F=BA=E7=A1=80=E6=A8=A1=E5=9D=97)?= =?UTF-8?q?:=20=E4=BF=AE=E5=A4=8Djs=E8=84=9A=E6=9C=AC=E4=B8=AD=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E4=BD=BF=E7=94=A8console=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/script/jsr223/JavaScriptFactory.java | 2 ++ .../community/script/jsr223/Jsr223ScriptFactory.java | 4 ++-- .../community/script/JavaScriptFactoryTest.java | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java index 49be7448..c6538c7b 100644 --- a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java +++ b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java @@ -30,6 +30,8 @@ public abstract class JavaScriptFactory extends Jsr223ScriptFactory { "this.eval = function(e){};" + "function readFully(){};" + "function readLine(){};" + + "const console=_$console;" + + "const utils=_$utils;" + "const print = function(e){console.log(e)};" + "const echo = print;"); diff --git a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/Jsr223ScriptFactory.java b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/Jsr223ScriptFactory.java index 433511d2..85a79127 100644 --- a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/Jsr223ScriptFactory.java +++ b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/Jsr223ScriptFactory.java @@ -42,10 +42,10 @@ public abstract class Jsr223ScriptFactory extends AbstractScriptFactory { ExecutionContext ctx = ExecutionContext.create(); - ctx.setAttribute("console", new Jsr223ScriptFactory.Console( + ctx.setAttribute("_$console", new Jsr223ScriptFactory.Console( LoggerFactory.getLogger("org.jetlinks.community.script." + script.getName())), ScriptContext.ENGINE_SCOPE); - ctx.setAttribute("utils", getUtils(), ScriptContext.ENGINE_SCOPE); + ctx.setAttribute("_$utils", getUtils(), ScriptContext.ENGINE_SCOPE); ctx.setAttribute("engine", null, ScriptContext.ENGINE_SCOPE); diff --git a/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/JavaScriptFactoryTest.java b/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/JavaScriptFactoryTest.java index 00f51687..275025a6 100644 --- a/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/JavaScriptFactoryTest.java +++ b/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/JavaScriptFactoryTest.java @@ -273,6 +273,18 @@ public abstract class JavaScriptFactoryTest { } + @Test + @SneakyThrows + void testLog() { + { + JavaScriptFactory factory = getFactory(); + + factory.compile(Script.of("test","console.log(123)")) + .call(); + + } + } + public interface Api { int add(int a, int b); -- Gitee From 67901c37326150f74f4393ad98870a8c03add3ec Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 23 Mar 2023 14:32:28 +0800 Subject: [PATCH 26/50] feat(maven): Update new r2dbc-mysql driver #mirromutth/r2dbc-mysql/issues/251 --- jetlinks-standalone/pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/jetlinks-standalone/pom.xml b/jetlinks-standalone/pom.xml index a37fe97b..b88a66f5 100644 --- a/jetlinks-standalone/pom.xml +++ b/jetlinks-standalone/pom.xml @@ -162,9 +162,16 @@ spring-boot-starter-data-r2dbc + + + + + + - dev.miku + io.asyncer r2dbc-mysql + 0.9.1 -- Gitee From dd2ea79640c796d68f431e10b84deb7bc1919a58 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 23 Mar 2023 14:32:47 +0800 Subject: [PATCH 27/50] =?UTF-8?q?refactor(=E5=9F=BA=E7=A1=80=E6=A8=A1?= =?UTF-8?q?=E5=9D=97):=20=E7=A7=BB=E9=99=A4=E6=97=A0=E7=94=A8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jetlinks/community/topic/Topics.java | 57 ------------------- 1 file changed, 57 deletions(-) diff --git a/jetlinks-components/common-component/src/main/java/org/jetlinks/community/topic/Topics.java b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/topic/Topics.java index c0e21569..3f0c0e1e 100755 --- a/jetlinks-components/common-component/src/main/java/org/jetlinks/community/topic/Topics.java +++ b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/topic/Topics.java @@ -11,63 +11,6 @@ import java.util.stream.Collectors; public interface Topics { - static String creator(String creatorId, String topic) { - return StringBuilderUtils.buildString(creatorId, topic, Topics::creator); - } - - static void creator(String creatorId, String topic, StringBuilder builder) { - builder.append("/user/").append(creatorId); - if (topic.charAt(0) != '/') { - builder.append('/'); - } - builder.append(topic); - } - - /** - * 根据绑定信息构造topic - * - * @param bindings 绑定信息 - * @param topic topic - * @return topic - */ - static List bindings(List> bindings, String topic) { - List topics = new ArrayList<>(bindings.size()); - for (Map binding : bindings) { - topics.add(binding(String.valueOf(binding.get("type")), String.valueOf(binding.get("id")), topic)); - } - return topics; - } - - static void binding(String type, String id, String topic, StringBuilder builder) { - builder.append('/') - .append(type) - .append('/') - .append(id); - if (topic.charAt(0) != '/') { - builder.append('/'); - } - builder.append(topic); - } - - static String binding(String type, String id, String topic) { - return StringBuilderUtils.buildString(type, id, topic, Topics::binding); - } - - @Deprecated - static String tenantMember(String memberId, String topic) { - if (!topic.startsWith("/")) { - topic = "/" + topic; - } - return String.join("", "/member/", memberId, topic); - } - - @Deprecated - static List tenantMembers(List members, String topic) { - return members - .stream() - .map(id -> tenantMember(id, topic)) - .collect(Collectors.toList()); - } String allDeviceRegisterEvent = "/_sys/registry-device/*/register"; String allDeviceUnRegisterEvent = "/_sys/registry-device/*/unregister"; -- Gitee From 547e495d56752156177887ccbabef10dfcf40b0f Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 24 Mar 2023 16:19:39 +0800 Subject: [PATCH 28/50] =?UTF-8?q?feat(=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86?= =?UTF-8?q?):=20=E5=A2=9E=E5=8A=A0=E4=BA=A7=E5=93=81=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E6=97=B6=E8=87=AA=E5=8A=A8=E5=90=8C=E6=AD=A5=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=88=B0=E8=AE=BE=E5=A4=87=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DeviceProductNameSynchronizer.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100755 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceProductNameSynchronizer.java diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceProductNameSynchronizer.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceProductNameSynchronizer.java new file mode 100755 index 00000000..46512a03 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceProductNameSynchronizer.java @@ -0,0 +1,121 @@ +package org.jetlinks.community.device.service; + +import lombok.AllArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.hswebframework.web.crud.events.EntityModifyEvent; +import org.hswebframework.web.crud.events.EntityPrepareCreateEvent; +import org.hswebframework.web.crud.events.EntityPrepareSaveEvent; +import org.hswebframework.web.crud.events.EntitySavedEvent; +import org.jetlinks.community.device.entity.DeviceInstanceEntity; +import org.jetlinks.community.device.entity.DeviceProductEntity; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 自动同步产品名称到设备表 + * + * @author zhouhao + * @since 1.6 + */ +@Component +@AllArgsConstructor +public class DeviceProductNameSynchronizer { + + private final LocalDeviceInstanceService instanceService; + private final LocalDeviceProductService productService; + + //自动更新产品名称 + @EventListener + public void autoUpdateProductName(EntityModifyEvent event) { + Map before = event.getBefore() + .stream() + .collect(Collectors.toMap(DeviceProductEntity::getId, Function.identity())); + + event.async( + Flux.fromIterable(event.getAfter()) + .filter(product -> StringUtils.hasText(product.getName()) + && before.get(product.getId()) != null && ( + !Objects.equals(before.get(product.getId()).getName(), product.getName()) + || + !Objects.equals(before.get(product.getId()).getDeviceType(), product.getDeviceType()) + ) + ) + .flatMap(product -> instanceService + .createUpdate() + .set(DeviceInstanceEntity::getProductName, product.getName()) + .set(DeviceInstanceEntity::getDeviceType, product.getDeviceType()) + .where(DeviceInstanceEntity::getProductId, product.getId()) + .execute()) + ); + } + + //新增设备前填充产品名称和类型等信息 + @EventListener + public void autoSetProductInfo(EntityPrepareCreateEvent event) { + + event.async( + applyProductToDevice(event.getEntity()) + ); + } + + //新增设备前填充产品名称和类型等信息 + @EventListener + public void autoSetProductInfo(EntityPrepareSaveEvent event) { + + event.async( + applyProductToDevice(event.getEntity()) + ); + } + + protected Mono applyProductToDevice(Collection devices) { + Set productId = devices + .stream() + .filter(device -> device.getProductName() == null || device.getDeviceType() == null) + .map(DeviceInstanceEntity::getProductId) + .collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(productId)) { + return Mono.empty(); + } + + return productService + .findById(productId) + .collectMap(DeviceProductEntity::getId, Function.identity()) + .doOnNext(mapping -> { + for (DeviceInstanceEntity device : devices) { + DeviceProductEntity product = mapping.get(device.getProductId()); + if (null != product) { + device.setProductName(product.getName()); + device.setDeviceType(product.getDeviceType()); + } + } + }) + .then(); + } + + //自动更新产品名称 + @EventListener + public void autoUpdateProductName(EntitySavedEvent event) { + event.async( + Flux.fromIterable(event.getEntity()) + .filter(product -> StringUtils.hasText(product.getName())) + .flatMap(product -> instanceService + .createUpdate() + .set(DeviceInstanceEntity::getProductName, product.getName()) + .set(DeviceInstanceEntity::getDeviceType, product.getDeviceType()) + .where(DeviceInstanceEntity::getProductId, product.getId()) + .not(DeviceInstanceEntity::getProductName, product.getName()) + .execute()) + ); + } +} -- Gitee From 4a421c980f292a51e585c19af1e25c83c7027126 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 27 Mar 2023 10:19:46 +0800 Subject: [PATCH 29/50] =?UTF-8?q?feat(=E7=9B=91=E6=8E=A7):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96micrometer=E5=88=9D=E5=A7=8B=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=8A=A0ignore=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimeSeriesMeterRegistryConfiguration.java | 2 ++ .../micrometer/TimeSeriesMeterRegistrySupplier.java | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistryConfiguration.java b/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistryConfiguration.java index aed70897..9ac3ebc4 100644 --- a/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistryConfiguration.java +++ b/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistryConfiguration.java @@ -2,6 +2,7 @@ package org.jetlinks.community.timeseries.micrometer; import io.micrometer.core.instrument.MeterRegistry; import org.jetlinks.community.timeseries.TimeSeriesManager; +import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -16,6 +17,7 @@ public class TimeSeriesMeterRegistryConfiguration { } @Bean + @ConditionalOnEnabledMetricsExport("simple") public MeterRegistry meterRegistry(TimeSeriesMeterRegistrySupplier registrySupplier) { // TODO: 2020/2/13 配置化 return registrySupplier.getMeterRegistry("jetlinks-metrics"); diff --git a/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistrySupplier.java b/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistrySupplier.java index bea178d8..e494cb12 100644 --- a/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistrySupplier.java +++ b/jetlinks-components/timeseries-component/src/main/java/org/jetlinks/community/timeseries/micrometer/TimeSeriesMeterRegistrySupplier.java @@ -2,6 +2,7 @@ package org.jetlinks.community.timeseries.micrometer; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.config.NamingConvention; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import lombok.Getter; import lombok.Setter; import org.jetlinks.community.micrometer.MeterRegistrySupplier; @@ -9,7 +10,9 @@ import org.jetlinks.community.timeseries.TimeSeriesManager; import org.jetlinks.community.timeseries.TimeSeriesMetric; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; public class TimeSeriesMeterRegistrySupplier implements MeterRegistrySupplier { @@ -29,6 +32,10 @@ public class TimeSeriesMeterRegistrySupplier implements MeterRegistrySupplier { @Setter private Map tags = new HashMap<>(); + @Getter + @Setter + private Set ignore = new HashSet<>(); + @Getter @Setter private Map metrics = new HashMap<>(); @@ -40,6 +47,9 @@ public class TimeSeriesMeterRegistrySupplier implements MeterRegistrySupplier { @Override public MeterRegistry getMeterRegistry(String metric, String... tagKeys) { + if (ignore.contains(metric)) { + return new SimpleMeterRegistry(); + } TimeSeriesMeterRegistry registry = new TimeSeriesMeterRegistry(timeSeriesManager, TimeSeriesMetric.of(metric), metrics.getOrDefault(metric, metrics.get("default")), -- Gitee From 8957c8b3868e32dd8fb2a8d794364edad2e4b6fd Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 27 Mar 2023 10:26:45 +0800 Subject: [PATCH 30/50] =?UTF-8?q?feat(=E6=97=A5=E5=BF=97):=20=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E6=97=A5=E5=BF=97=E5=A2=9E=E5=8A=A0=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/logging/access/AccessLoggingTranslator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jetlinks-components/logging-component/src/main/java/org/jetlinks/community/logging/access/AccessLoggingTranslator.java b/jetlinks-components/logging-component/src/main/java/org/jetlinks/community/logging/access/AccessLoggingTranslator.java index 39a7406d..371a0579 100644 --- a/jetlinks-components/logging-component/src/main/java/org/jetlinks/community/logging/access/AccessLoggingTranslator.java +++ b/jetlinks-components/logging-component/src/main/java/org/jetlinks/community/logging/access/AccessLoggingTranslator.java @@ -2,6 +2,7 @@ package org.jetlinks.community.logging.access; import org.hswebframework.web.logging.events.AccessLoggerAfterEvent; import org.jetlinks.community.logging.configuration.LoggingProperties; +import org.jetlinks.core.utils.TopicUtils; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @@ -20,6 +21,11 @@ public class AccessLoggingTranslator { @EventListener public void translate(AccessLoggerAfterEvent event) { + for (String pathExclude : properties.getAccess().getPathExcludes()) { + if (TopicUtils.match(pathExclude, event.getLogger().getUrl())) { + return; + } + } eventPublisher.publishEvent(SerializableAccessLog.of(event.getLogger())); } -- Gitee From 0ce219c04fb45b1a8c8f132c97117c000b212059 Mon Sep 17 00:00:00 2001 From: ayan Date: Thu, 30 Mar 2023 16:17:13 +0800 Subject: [PATCH 31/50] =?UTF-8?q?fix=EF=BC=88=E8=8F=9C=E5=8D=95=E7=AE=A1?= =?UTF-8?q?=E7=90=86=EF=BC=89=E6=B7=BB=E5=8A=A0=E8=8F=9C=E5=8D=95ID?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E6=97=B6=E7=9A=84=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/auth/entity/MenuEntity.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java index 3100e5ac..f1daa479 100755 --- a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java +++ b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java @@ -5,11 +5,15 @@ import lombok.Getter; import lombok.Setter; import org.apache.commons.collections4.CollectionUtils; import org.hibernate.validator.constraints.Length; -import org.hswebframework.ezorm.rdb.mapping.annotation.*; +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.JsonCodec; import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity; import org.hswebframework.web.api.crud.entity.RecordCreationEntity; import org.hswebframework.web.crud.annotation.EnableEntityEvent; import org.hswebframework.web.crud.generator.Generators; +import org.hswebframework.web.utils.DigestUtils; import org.hswebframework.web.validator.CreateGroup; import javax.persistence.Column; @@ -118,6 +122,23 @@ public class MenuEntity ) private Long createTime; + @Override + public String getId() { + if (super.getId() == null) { + generateId(); + } + return super.getId(); + } + + public void generateId() { + String id = generateHexId(code, owner); + setId(id); + } + + public static String generateHexId(String boardId, String owner) { + return DigestUtils.md5Hex(String.join(boardId, "|", owner)); + } + public boolean isSupportDataAccess() { return false; } -- Gitee From 887bda8ebfcc2aef9b6e911cc8c9618bf5a90db7 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 7 Apr 2023 10:35:23 +0800 Subject: [PATCH 32/50] =?UTF-8?q?feat(=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86?= =?UTF-8?q?):=20=E9=80=8F=E4=BC=A0=E6=B6=88=E6=81=AF=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=AD=90=E8=AE=BE=E5=A4=87=E4=BC=9A=E8=AF=9D?= =?UTF-8?q?=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gateway/DeviceGatewayHelper.java | 42 +++++++++++-------- .../TransparentDeviceMessageConnector.java | 34 +++++++++++---- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/DeviceGatewayHelper.java b/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/DeviceGatewayHelper.java index edf8d6d0..3abdbaf7 100755 --- a/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/DeviceGatewayHelper.java +++ b/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/DeviceGatewayHelper.java @@ -1,6 +1,7 @@ package org.jetlinks.community.gateway; import lombok.AllArgsConstructor; +import lombok.Getter; import org.jetlinks.core.device.DeviceConfigKey; import org.jetlinks.core.device.DeviceOperator; import org.jetlinks.core.device.DeviceRegistry; @@ -35,8 +36,11 @@ import java.util.function.Supplier; @AllArgsConstructor public class DeviceGatewayHelper { + @Getter private final DeviceRegistry registry; + @Getter private final DeviceSessionManager sessionManager; + @Getter private final DecodedClientMessageHandler messageHandler; public static Consumer applySessionKeepaliveTimeout(DeviceMessage msg, Supplier timeoutSupplier) { @@ -136,6 +140,7 @@ public class DeviceGatewayHelper { } })); + //子设备注册 if (isDoRegister(children)) { return this @@ -182,7 +187,7 @@ public class DeviceGatewayHelper { if (l == 0) { return registry .getDevice(deviceId) - .flatMap(device -> messageHandler.handleMessage(device, message)); + .flatMap(device -> handleMessage(device, message)); } return Mono.empty(); }) @@ -196,28 +201,22 @@ public class DeviceGatewayHelper { .orElse(false); } + if (then == null) { + then = registry.getDevice(deviceId); + } + //忽略会话管理,比如一个设备存在多种接入方式时,其中一种接入方式收到的消息设置忽略会话来防止会话冲突 if (message.getHeaderOrDefault(Headers.ignoreSession)) { - return registry - .getDevice(deviceId) - .flatMap(device -> { - if (!isDoRegister(message)) { - return messageHandler - .handleMessage(device, message) - .thenReturn(device); - } - return Mono.just(device); - }); - - } + if (!isDoRegister(message)) { + return handleMessage(null, message) + .then(then); + } + return then; - if (then == null) { - then = registry.getDevice(deviceId); } if (doHandle) { - then = messageHandler - .handleMessage(null, message) + then = handleMessage(null, message) .then(then); } @@ -229,6 +228,13 @@ public class DeviceGatewayHelper { } + private Mono handleMessage(DeviceOperator device, Message message) { + return messageHandler + .handleMessage(device, message) + //转换为empty,减少触发discard + .flatMap(ignore -> Mono.empty()); + } + private Mono createOrUpdateSession(String deviceId, DeviceMessage message, Function> sessionBuilder, @@ -256,7 +262,7 @@ public class DeviceGatewayHelper { () -> { //设备注册 if (isDoRegister(message)) { - return messageHandler + return this .handleMessage(null, message) //延迟2秒后尝试重新获取设备并上线 .then(Mono.delay(Duration.ofSeconds(2))) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java index 22f6e27e..c902a668 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/transparent/TransparentDeviceMessageConnector.java @@ -12,13 +12,14 @@ import org.hswebframework.web.crud.events.EntityModifyEvent; import org.hswebframework.web.crud.events.EntitySavedEvent; import org.hswebframework.web.exception.ValidationException; import org.jctools.maps.NonBlockingHashMap; +import org.jetlinks.community.gateway.DeviceGatewayHelper; import org.jetlinks.core.device.DeviceConfigKey; import org.jetlinks.core.device.DeviceOperator; +import org.jetlinks.core.device.DeviceRegistry; +import org.jetlinks.core.device.session.DeviceSessionManager; import org.jetlinks.core.event.EventBus; import org.jetlinks.core.event.Subscription; -import org.jetlinks.core.message.DeviceMessage; -import org.jetlinks.core.message.DirectDeviceMessage; -import org.jetlinks.core.message.Headers; +import org.jetlinks.core.message.*; import org.jetlinks.core.message.interceptor.DeviceMessageSenderInterceptor; import org.jetlinks.community.OperationSource; import org.jetlinks.community.device.entity.TransparentMessageCodecEntity; @@ -45,14 +46,19 @@ public class TransparentDeviceMessageConnector implements CommandLineRunner, Dev private final Map codecs = new NonBlockingHashMap<>(); + private final DeviceGatewayHelper gatewayHelper; + public TransparentDeviceMessageConnector(@SuppressWarnings("all") - ReactiveRepository repository, + ReactiveRepository repository, DecodedClientMessageHandler messageHandler, + DeviceSessionManager sessionManager, + DeviceRegistry registry, EventBus eventBus, ObjectProvider providers) { this.repository = repository; this.messageHandler = messageHandler; this.eventBus = eventBus; + this.gatewayHelper = new DeviceGatewayHelper(registry, sessionManager, messageHandler); for (TransparentMessageCodecProvider provider : providers) { TransparentMessageCodecProviders.addProvider(provider); } @@ -69,10 +75,24 @@ public class TransparentDeviceMessageConnector implements CommandLineRunner, Dev } return codec .decode(message) - .flatMap(msg -> messageHandler.handleMessage(null, msg)) + .flatMap(this::handleMessage) .then(); } + private Mono handleMessage(DeviceMessage msg) { + if (msg instanceof ChildDeviceMessage || msg instanceof ChildDeviceMessageReply) { + msg.addHeader(Headers.ignoreSession, true); + return gatewayHelper + .handleDeviceMessage( + msg, + device -> null + ) + .then(); + } + + return messageHandler.handleMessage(null, msg).then(); + } + private TransparentMessageCodec getCodecOrNull(String productId, String deviceId) { CacheKey cacheKey = new CacheKey(productId, deviceId); TransparentMessageCodec codec = codecs.get(cacheKey); @@ -94,7 +114,7 @@ public class TransparentDeviceMessageConnector implements CommandLineRunner, Dev msg.addHeader("encodeBy", message.getMessageType().name()); //所有透传消息都设置为异步 msg.addHeader(Headers.async, true); - // msg.addHeader(Headers.sendAndForget, true); + // msg.addHeader(Headers.sendAndForget, true); }) ) .defaultIfEmpty(message); @@ -110,7 +130,7 @@ public class TransparentDeviceMessageConnector implements CommandLineRunner, Dev return provider .createCodec(entity.getConfiguration()) .doOnNext(codec -> codecs.put(key, codec)) - .contextWrite(OperationSource.ofContext(entity.getId(),null,entity)) + .contextWrite(OperationSource.ofContext(entity.getId(), null, entity)) .switchIfEmpty(Mono.fromRunnable(() -> codecs.remove(key))) .then(); } -- Gitee From e6e400b365f6a00c9d5d6a48dc277f8675158d8e Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Fri, 7 Apr 2023 15:55:26 +0800 Subject: [PATCH 33/50] =?UTF-8?q?fix(=E9=98=BF=E9=87=8C=E4=BA=91=E7=9F=AD?= =?UTF-8?q?=E4=BF=A1):=20=E8=A7=A3=E5=86=B3=E7=9F=AD=E4=BF=A1=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=92=8C=E6=A0=87=E7=AD=BE=E5=8F=AA=E8=83=BD=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E7=AC=AC=E4=B8=80=E9=A1=B5=E6=95=B0=E6=8D=AE=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#257)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notify/sms/aliyun/AliyunSmsNotifier.java | 42 ++++++++++++++++--- .../sms/aliyun/web/AliyunSmsController.java | 2 +- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsNotifier.java b/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsNotifier.java index 31703361..626be4af 100755 --- a/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsNotifier.java +++ b/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsNotifier.java @@ -32,7 +32,10 @@ import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import javax.annotation.Nonnull; +import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @@ -164,24 +167,51 @@ public class AliyunSmsNotifier extends AbstractNotifier { * @return 短信签名集合 */ public Flux getSmsSigns() { - return Mono - .fromCallable(() -> client.getAcsResponse(new QuerySmsSignListRequest())) - .flatMapIterable(QuerySmsSignListResponse::getSmsSignList) + return doQuerySmsSigns(new AtomicInteger(0), 50) + .flatMapIterable(Function.identity()) .map(SmsSign::of) .as(FluxTracer.create("/aliyun/sms/sign")) .onErrorResume(err -> Mono.empty()); } + /** * @return 短信模板集合 */ public Flux getSmsTemplates() { - return Mono - .fromCallable(() -> client.getAcsResponse(new QuerySmsTemplateListRequest())) - .flatMapIterable(QuerySmsTemplateListResponse::getSmsTemplateList) + return doQuerySmsTemplates(new AtomicInteger(0), 50) + .flatMapIterable(Function.identity()) .map(SmsTemplate::of) .as(FluxTracer.create("/aliyun/sms/template")) .onErrorResume(err -> Mono.empty()); + } + + public Flux> doQuerySmsSigns(AtomicInteger pageIndex, int pageSize) { + QuerySmsSignListRequest request = new QuerySmsSignListRequest(); + request.setPageSize(pageSize); + request.setPageIndex(pageIndex.incrementAndGet()); + return Mono + .fromCallable(() -> client.getAcsResponse(request).getSmsSignList()) + .expand(dtos -> { + if (dtos.size() == pageSize){ + return doQuerySmsSigns(pageIndex, pageSize); + } + return Flux.empty(); + }); + } + + public Flux> doQuerySmsTemplates(AtomicInteger pageIndex, int pageSize) { + QuerySmsTemplateListRequest request = new QuerySmsTemplateListRequest(); + request.setPageSize(pageSize); + request.setPageIndex(pageIndex.incrementAndGet()); + return Mono + .fromCallable(() -> client.getAcsResponse(request).getSmsTemplateList()) + .expand(dtos -> { + if (dtos.size() == pageSize){ + return doQuerySmsTemplates(pageIndex, pageSize); + } + return Flux.empty(); + }); } } diff --git a/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/web/AliyunSmsController.java b/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/web/AliyunSmsController.java index 3c215903..81d2852f 100644 --- a/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/web/AliyunSmsController.java +++ b/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/web/AliyunSmsController.java @@ -41,7 +41,7 @@ public class AliyunSmsController { @GetMapping("/{configId}/templates") @QueryAction - @Operation(summary = "获取短信标签列表") + @Operation(summary = "获取短信模板列表") public Flux getAliyunSmsTemplates(@PathVariable String configId) { return notifierManager .getNotifier(DefaultNotifyType.sms, configId) -- Gitee From b0d7b651486cef1c971b8dfc1a7c2d5804f206b5 Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Fri, 7 Apr 2023 17:22:05 +0800 Subject: [PATCH 34/50] =?UTF-8?q?feat(=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?):=20=E6=B7=BB=E5=8A=A0=E8=AE=BE=E5=A4=87=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E6=9E=84=E9=80=A0=E5=99=A8=20(#259)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/term/DeviceCategoryTerm.java | 65 ++++++++++++ .../service/term/DeviceInstanceTerm.java | 99 +++++++++++++++++++ .../term/DeviceProductInfoTermBuilder.java | 85 ++++++++++++++++ .../service/term/DeviceProtocolTerm.java | 34 +++++++ .../device/service/term/DeviceTypeTerm.java | 37 +++++++ 5 files changed, 320 insertions(+) create mode 100755 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceCategoryTerm.java create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceInstanceTerm.java create mode 100755 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProductInfoTermBuilder.java create mode 100755 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProtocolTerm.java create mode 100755 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceTypeTerm.java diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceCategoryTerm.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceCategoryTerm.java new file mode 100755 index 00000000..b9f5e551 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceCategoryTerm.java @@ -0,0 +1,65 @@ +package org.jetlinks.community.device.service.term; + +import org.hswebframework.ezorm.core.param.Term; +import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.PrepareSqlFragments; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.SqlFragments; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.term.AbstractTermFragmentBuilder; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 根据产品分类查询与产品关联的数据,如: 查询某个分类下的产品列表. + *

+ * + * 注意: 查询时指定列名是和产品ID关联的列或者实体类属性名. + * 如: 查询设备列表时则使用productId. + * 此条件仅支持关系型数据库中的查询. + * + *

+ * 在通用查询接口中可以使用动态查询参数中的term.termType来使用此功能. + * 查看动态查询参数说明 + *

+ * 在内部通用条件中,可以使用DSL方式创建条件,例如: + *

+ *     createQuery()
+ *     .where()
+ *     .and("productId","dev-prod-cat",cateId)
+ *     .fetch()
+ * 
+ * + * @author zhouhao + * @since 1.3 + */ +@Component +public class DeviceCategoryTerm extends AbstractTermFragmentBuilder { + + public DeviceCategoryTerm() { + super("dev-prod-cat", "按产品品类查询"); + } + + @Override + public SqlFragments createFragments(String columnFullName, RDBColumnMetadata column, Term term) { + + PrepareSqlFragments sqlFragments = PrepareSqlFragments.of(); + + List idList = convertList(column, term); + + sqlFragments.addSql("exists(select 1 from dev_product prod where prod.id =", columnFullName); + + sqlFragments.addSql("and exists(select 1 from dev_product_category g where g.id = prod.classified_id and "); + sqlFragments.addSql( + idList + .stream() + .map(r -> "path like (select concat(path,'%') from dev_product_category g2 where g2.id = ?)") + .collect(Collectors.joining(" or ", "(", ")")) + , ")") + .addParameter(idList); + + sqlFragments.addSql(")"); + + return sqlFragments; + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceInstanceTerm.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceInstanceTerm.java new file mode 100644 index 00000000..bee5e6d7 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceInstanceTerm.java @@ -0,0 +1,99 @@ +package org.jetlinks.community.device.service.term; + +import org.hswebframework.ezorm.core.param.Term; +import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; +import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata; +import org.hswebframework.ezorm.rdb.metadata.TableOrViewMetadata; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.*; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.term.AbstractTermFragmentBuilder; +import org.jetlinks.community.utils.ConverterUtils; +import org.springframework.stereotype.Component; + +import java.util.List; + + +/** + * 根据设备查询. + *

+ * 将设备信息的条件嵌套到此条件中 + *

+ *

+ * "terms": [
+ *      {
+ *          "column": "device_id$dev-instance",
+ *          "value": [
+ *              {
+ *                  "column": "product_id",
+ *                  "termType": "eq",
+ *                  "value": "1"
+ *              }
+ *          ]
+ *      }
+ * ],
+ * 
+ * + * @author zhouhao + * @since 1.6 + */ +@Component +public class DeviceInstanceTerm extends AbstractTermFragmentBuilder { + + public static final String termType = "dev-instance"; + + public DeviceInstanceTerm() { + super(termType, "根据设备信息查询"); + } + + @Override + public SqlFragments createFragments(String columnFullName, + RDBColumnMetadata column, + Term term) { + List terms = ConverterUtils.convertTerms(term.getValue()); + PrepareSqlFragments sqlFragments = PrepareSqlFragments.of(); + if (term.getOptions().contains("not")) { + sqlFragments.addSql("not"); + } + sqlFragments.addSql("exists(select 1 from ", getTableName("dev_device_instance", column), " _dev where _dev.id = ", columnFullName); + + RDBTableMetadata metadata = column + .getOwner() + .getSchema() + .getTable("dev_device_instance") + .orElseThrow(() -> new UnsupportedOperationException("unsupported dev_device_instance")); + + SqlFragments where = builder.createTermFragments(metadata, terms); + if (!where.isEmpty()) { + sqlFragments.addSql("and") + .addFragments(where); + } + sqlFragments.addSql(")"); + return sqlFragments; + } + + + static DeviceTermsBuilder builder = new DeviceTermsBuilder(); + + static class DeviceTermsBuilder extends AbstractTermsFragmentBuilder { + + @Override + protected SqlFragments createTermFragments(TableOrViewMetadata parameter, + List terms) { + return super.createTermFragments(parameter, terms); + } + + @Override + protected SqlFragments createTermFragments(TableOrViewMetadata table, + Term term) { + if (term.getValue() instanceof NativeSql) { + NativeSql sql = ((NativeSql) term.getValue()); + return PrepareSqlFragments.of(sql.getSql(), sql.getParameters()); + } + return table + .getColumn(term.getColumn()) + .flatMap(column -> table + .findFeature(TermFragmentBuilder.createFeatureId(term.getTermType())) + .map(termFragment -> termFragment.createFragments(column.getFullName("_dev"), column, term))) + .orElse(EmptySqlFragments.INSTANCE); + } + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProductInfoTermBuilder.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProductInfoTermBuilder.java new file mode 100755 index 00000000..37179c71 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProductInfoTermBuilder.java @@ -0,0 +1,85 @@ +package org.jetlinks.community.device.service.term; + +import org.hswebframework.ezorm.core.param.Term; +import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; +import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata; +import org.hswebframework.ezorm.rdb.metadata.TableOrViewMetadata; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.*; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.term.AbstractTermFragmentBuilder; +import org.jetlinks.community.utils.ConverterUtils; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 根据设备产品信息查询设备数据 + * + * @author bestfeng + * @since 2.0 + */ +@Component +public class DeviceProductInfoTermBuilder extends AbstractTermFragmentBuilder { + + public static final String termType = "product-info"; + + public DeviceProductInfoTermBuilder() { + super(termType, "根据产品信息查询设备数据"); + } + + + @SuppressWarnings("all") + public static List convertTerms(Object value) { + return ConverterUtils.convertTerms(value); + } + + + @Override + public SqlFragments createFragments(String columnFullName, RDBColumnMetadata column, Term term) { + List terms = convertTerms(term.getValue()); + PrepareSqlFragments sqlFragments = PrepareSqlFragments.of(); + if(term.getOptions().contains("not")){ + sqlFragments.addSql("not"); + } + sqlFragments + .addSql("exists(select 1 from ",getTableName("dev_product",column)," _product where _product.id = ", columnFullName); + + RDBTableMetadata metadata = column + .getOwner() + .getSchema() + .getTable("dev_product") + .orElseThrow(() -> new UnsupportedOperationException("unsupported dev_product")); + + SqlFragments where = builder.createTermFragments(metadata, terms); + if (!where.isEmpty()) { + sqlFragments.addSql("and") + .addFragments(where); + } + sqlFragments.addSql(")"); + return sqlFragments; + } + + + static ProductTermBuilder builder = new ProductTermBuilder(); + + static class ProductTermBuilder extends AbstractTermsFragmentBuilder { + + @Override + protected SqlFragments createTermFragments(TableOrViewMetadata parameter, List terms) { + return super.createTermFragments(parameter, terms); + } + + @Override + protected SqlFragments createTermFragments(TableOrViewMetadata table, Term term) { + if (term.getValue() instanceof NativeSql) { + NativeSql sql = ((NativeSql) term.getValue()); + return PrepareSqlFragments.of(sql.getSql(), sql.getParameters()); + } + return table + .getColumn(term.getColumn()) + .flatMap(column -> table + .findFeature(TermFragmentBuilder.createFeatureId(term.getTermType())) + .map(termFragment -> termFragment.createFragments(column.getFullName("_product"), column, term))) + .orElse(EmptySqlFragments.INSTANCE); + } + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProtocolTerm.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProtocolTerm.java new file mode 100755 index 00000000..b4e86ae4 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceProtocolTerm.java @@ -0,0 +1,34 @@ +package org.jetlinks.community.device.service.term; + +import org.hswebframework.ezorm.core.param.Term; +import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.PrepareSqlFragments; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.SqlFragments; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.term.AbstractTermFragmentBuilder; +import org.springframework.stereotype.Component; + +import java.util.List; + + +@Component +public class DeviceProtocolTerm extends AbstractTermFragmentBuilder { + public DeviceProtocolTerm() { + super("dev-protocol", "按协议查询设备"); + } + + @Override + public SqlFragments createFragments(String columnFullName, RDBColumnMetadata column, Term term) { + PrepareSqlFragments sqlFragments = PrepareSqlFragments.of(); + List idList = convertList(column, term); + if (term.getOptions().contains("not")) { + sqlFragments.addSql("not"); + } + sqlFragments + .addSql("exists(select 1 from ",getTableName("dev_product",column)," _product where _product.id = " + columnFullName); + sqlFragments + .addSql(" and _product.message_protocol = ?"); + sqlFragments.addSql(")").addParameter(idList); + + return sqlFragments; + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceTypeTerm.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceTypeTerm.java new file mode 100755 index 00000000..2b42a7e0 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/term/DeviceTypeTerm.java @@ -0,0 +1,37 @@ +package org.jetlinks.community.device.service.term; + +import org.hswebframework.ezorm.core.param.Term; +import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.PrepareSqlFragments; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.SqlFragments; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.term.AbstractTermFragmentBuilder; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + + +@Component +public class DeviceTypeTerm extends AbstractTermFragmentBuilder { + public DeviceTypeTerm() { + super("dev-device-type", "按设备类型查询设备"); + } + + @Override + public SqlFragments createFragments(String columnFullName, RDBColumnMetadata column, Term term) { + PrepareSqlFragments sqlFragments = PrepareSqlFragments.of(); + List idList = convertList(column, term); + if (term.getOptions().contains("not")) { + sqlFragments.addSql("not"); + } + sqlFragments + .addSql("exists(select 1 from ",getTableName("dev_product",column)," _product where _product.id = " + columnFullName); + sqlFragments + .addSql(" and _product.device_type in("); + sqlFragments.addSql(idList.stream().map(str -> "?").collect(Collectors.joining(","))) + .addParameter(idList) + .addSql("))"); + + return sqlFragments; + } +} -- Gitee From 9a3d67e3fb1ab3c8ce1844e2065b56176b87f318 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 13 Apr 2023 16:58:04 +0800 Subject: [PATCH 35/50] =?UTF-8?q?refactor(=E9=85=8D=E7=BD=AE):=20=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E5=9C=B0=E5=9D=80=E4=BD=BF=E7=94=A8127.0.0.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jetlinks-standalone/src/main/resources/application.yml b/jetlinks-standalone/src/main/resources/application.yml index bcff5d1b..ccd8528e 100644 --- a/jetlinks-standalone/src/main/resources/application.yml +++ b/jetlinks-standalone/src/main/resources/application.yml @@ -26,8 +26,8 @@ spring: # max-wait: 10s r2dbc: # 需要手动创建数据库,启动会自动创建表,修改了配置easyorm相关配置也要修改 - url: r2dbc:postgresql://localhost:5432/jetlinks - # url: r2dbc:mysql://localhost:3306/jetlinks?ssl=false&serverZoneId=Asia/Shanghai # 修改了配置easyorm相关配置也要修改 + url: r2dbc:postgresql://127.0.0.1:5432/jetlinks + # url: r2dbc:mysql://127.0.0.1:3306/jetlinks?ssl=false&serverZoneId=Asia/Shanghai # 修改了配置easyorm相关配置也要修改 username: postgres password: jetlinks pool: @@ -39,7 +39,7 @@ spring: debug-agent: enabled: false elasticsearch: - uris: localhost:9200 + uris: 127.0.0.1:9200 socket-timeout: 10s connection-timeout: 15s webclient: @@ -52,7 +52,7 @@ tdengine: database: jetlinks restful: endpoints: - - http://localhost:6041/ + - http://127.0.0.1:6041/ username: root password: taosdata elasticsearch: @@ -88,7 +88,7 @@ hsweb: file: upload: static-file-path: ./static/upload - static-location: http://localhost:8848/upload + static-location: http://127.0.0.1:8848/upload webflux: response-wrapper: enabled: true #开启响应包装器(将返回值包装为ResponseMessage) @@ -176,7 +176,7 @@ system: properties: - key: base-path name: 接口根路径 - default-value: http://localhost:9000/api + default-value: http://127.0.0.1:9000/api - id: amap name: 高德地图配置 public-access: false -- Gitee From 037c790550073149e3b166637bc9b71392d0cf72 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 14 Apr 2023 17:50:10 +0800 Subject: [PATCH 36/50] =?UTF-8?q?fix(TDEngine):=20=E4=BF=AE=E5=A4=8DTDEngi?= =?UTF-8?q?ne=E6=95=B0=E6=8D=AE=E5=BA=93=E4=BA=8B=E4=BB=B6=E7=B2=BE?= =?UTF-8?q?=E5=BA=A6=E4=B8=8D=E6=98=AF=E6=AF=AB=E7=A7=92=E6=97=B6=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=8C=89=E6=97=B6=E9=97=B4=E6=9F=A5=E8=AF=A2=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jetlinks/community/tdengine/TDEngineUtils.java | 10 ++++++++++ .../tdengine/things/TDengineThingDataHelper.java | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java b/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java index 34ef572e..8e1d5275 100644 --- a/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java +++ b/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/TDEngineUtils.java @@ -3,12 +3,22 @@ package org.jetlinks.community.tdengine; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; import org.springframework.web.reactive.function.client.ClientResponse; import reactor.core.publisher.Mono; @Slf4j public class TDEngineUtils { + public static final DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + + public static String formatTime(long timestamp) { + return new DateTime(timestamp).toString(format); + } + public static Mono checkExecuteResult(ClientResponse response) { if (response.statusCode().isError()) { diff --git a/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/things/TDengineThingDataHelper.java b/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/things/TDengineThingDataHelper.java index 98dff050..b4a5a74c 100644 --- a/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/things/TDengineThingDataHelper.java +++ b/jetlinks-components/tdengine-component/src/main/java/org/jetlinks/community/tdengine/things/TDengineThingDataHelper.java @@ -11,6 +11,7 @@ import org.hswebframework.utils.time.DefaultDateFormatter; import org.hswebframework.web.api.crud.entity.PagerResult; import org.hswebframework.web.api.crud.entity.QueryParamEntity; import org.hswebframework.web.exception.BusinessException; +import org.jetlinks.community.tdengine.TDEngineUtils; import org.jetlinks.community.tdengine.term.TDengineQueryConditionBuilder; import org.jetlinks.core.metadata.Converter; import org.jetlinks.core.metadata.DataType; @@ -114,9 +115,9 @@ class TDengineThingDataHelper implements Disposable { public static Object prepareTimestampValue(Object value, String type) { - return ConverterUtils.tryConvertToList(value,v->{ + return ConverterUtils.tryConvertToList(value, v -> { Date date = CastUtils.castDate(v); - return date.getTime(); + return TDEngineUtils.formatTime(date.getTime()); }); } -- Gitee From dc4b582fe7d7c609ab5783e3fd4759751b57aaa4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 09:34:31 +0800 Subject: [PATCH 37/50] Bump json from 20180130 to 20230227 (#264) Bumps [json](https://github.com/douglascrockford/JSON-java) from 20180130 to 20230227. - [Release notes](https://github.com/douglascrockford/JSON-java/releases) - [Changelog](https://github.com/stleary/JSON-java/blob/master/docs/RELEASES.md) - [Commits](https://github.com/douglascrockford/JSON-java/commits) --- updated-dependencies: - dependency-name: org.json:json dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df0b0263..72ffe9ac 100644 --- a/pom.xml +++ b/pom.xml @@ -198,7 +198,7 @@ org.json json - 20180130 + 20230227 -- Gitee From 5fc41d5bf1aa2286b0cd63d6338a1e2cb225db1e Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:52:30 +0800 Subject: [PATCH 38/50] =?UTF-8?q?feat(=E4=BA=A7=E5=93=81):=20=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E6=8C=87=E5=AE=9A=E7=9A=84=E6=8E=A5=E5=85=A5=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E8=8E=B7=E5=8F=96=E4=BA=A7=E5=93=81=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E9=85=8D=E7=BD=AE=E5=AE=9A=E4=B9=89=20(#266)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../supports/DeviceGatewayProperties.java | 3 +++ .../DefaultDeviceConfigMetadataManager.java | 18 ++++++++++++++++++ .../DefaultDeviceConfigMetadataSupplier.java | 14 ++++++++++++++ .../service/DeviceConfigMetadataManager.java | 19 +++++++++++++++++++ .../spi/DeviceConfigMetadataSupplier.java | 8 ++++++++ .../device/web/DeviceProductController.java | 10 ++++++++++ 6 files changed, 72 insertions(+) diff --git a/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/supports/DeviceGatewayProperties.java b/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/supports/DeviceGatewayProperties.java index 422e3846..4601c200 100644 --- a/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/supports/DeviceGatewayProperties.java +++ b/jetlinks-components/gateway-component/src/main/java/org/jetlinks/community/gateway/supports/DeviceGatewayProperties.java @@ -31,6 +31,9 @@ public class DeviceGatewayProperties implements ValueObject { private String protocol; + private String transport; + + private Map configuration=new HashMap<>(); @Override diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java index d038291b..896cc39c 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java @@ -1,5 +1,6 @@ package org.jetlinks.community.device.service; +import lombok.extern.slf4j.Slf4j; import org.jetlinks.community.device.spi.DeviceConfigMetadataSupplier; import org.jetlinks.core.metadata.*; import org.springframework.beans.factory.config.BeanPostProcessor; @@ -13,6 +14,7 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @Component +@Slf4j public class DefaultDeviceConfigMetadataManager implements DeviceConfigMetadataManager, BeanPostProcessor { private final List suppliers = new CopyOnWriteArrayList<>(); @@ -62,6 +64,22 @@ public class DefaultDeviceConfigMetadataManager implements DeviceConfigMetadataM .filter(meta -> org.apache.commons.collections4.CollectionUtils.isNotEmpty(meta.getProperties())); } + + @Override + public Flux getProductConfigMetadataByAccessId(String productId, + String accessId) { + return Flux.fromIterable(suppliers) + .flatMap(supplier -> supplier + .getProductConfigMetadataByAccessId(productId, accessId) + .onErrorResume(e -> { + log.error("get product config metatada by gateway error", e); + return Flux.empty(); + })) + .map(config -> config.copy(DeviceConfigScope.product)) + .filter(config -> !CollectionUtils.isEmpty(config.getProperties())) + .sort(Comparator.comparing(ConfigMetadata::getName)); + } + @Override public Object postProcessAfterInitialization(@Nonnull Object bean, @Nonnull String beanName) { if (bean instanceof DeviceConfigMetadataSupplier) { diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataSupplier.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataSupplier.java index c32a16e7..d74a0d33 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataSupplier.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataSupplier.java @@ -5,6 +5,7 @@ import org.hswebframework.web.exception.BusinessException; import org.jetlinks.community.device.entity.DeviceInstanceEntity; import org.jetlinks.community.device.entity.DeviceProductEntity; import org.jetlinks.community.device.spi.DeviceConfigMetadataSupplier; +import org.jetlinks.community.gateway.supports.DeviceGatewayPropertiesManager; import org.jetlinks.core.ProtocolSupport; import org.jetlinks.core.ProtocolSupports; import org.jetlinks.core.message.codec.Transport; @@ -32,6 +33,8 @@ public class DefaultDeviceConfigMetadataSupplier implements DeviceConfigMetadata private final ProtocolSupports protocolSupports; + private final DeviceGatewayPropertiesManager gatewayPropertiesManager; + @Override @SuppressWarnings("all") public Flux getDeviceConfigMetadata(String deviceId) { @@ -79,6 +82,17 @@ public class DefaultDeviceConfigMetadataSupplier implements DeviceConfigMetadata .flatMapMany(Function.identity()); } + @Override + public Flux getProductConfigMetadataByAccessId(String productId, + String accessId) { + return gatewayPropertiesManager + .getProperties(accessId) + .flatMapMany(properties -> protocolSupports + .getProtocol(properties.getProtocol()) + .onErrorMap(e -> new BusinessException("error.unable_to_load_protocol_by_access_id", 404, properties.getProtocol())) + .flatMap(support -> support.getConfigMetadata(Transport.of(properties.getTransport())))); + } + private Flux getProductConfigMetadata0(String productId) { return productService .findById(productId) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java index aa79a612..61422fce 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java @@ -75,6 +75,25 @@ public interface DeviceConfigMetadataManager { String typeId, ConfigScope... scopes); + + /** + * 根据产品ID和网关ID获取配置信息 + *

+ * 使用指定的接入方式查询,忽略产品当前绑定的接入方式 + *

+ * 当配置来自产品绑定关系时,可根据productId查询 + *

+ * 当配置来自接入方式时,可根据accessId查询 + *

+ * 当配置来自协议包时,可根据accessId关联的协议查询 + * + * @param productId 产品ID + * @param accessId 网关ID + * @return 配置信息 + */ + Flux getProductConfigMetadataByAccessId(String productId, + String accessId); + Flux getProductFeatures(String productId); } diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/spi/DeviceConfigMetadataSupplier.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/spi/DeviceConfigMetadataSupplier.java index 6e650098..c62065e5 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/spi/DeviceConfigMetadataSupplier.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/spi/DeviceConfigMetadataSupplier.java @@ -41,6 +41,14 @@ public interface DeviceConfigMetadataSupplier { return Flux.empty(); } + /** + * @see org.jetlinks.community.device.service.DeviceConfigMetadataManager#getProductConfigMetadataByAccessId(String, String) + */ + @Generated + default Flux getProductConfigMetadataByAccessId(String productId, String accessId) { + return Flux.empty(); + } + /** * @see org.jetlinks.community.device.service.DeviceConfigMetadataManager#getProductFeatures(String) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceProductController.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceProductController.java index 2869b1cb..aacacd8c 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceProductController.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceProductController.java @@ -97,6 +97,16 @@ public class DeviceProductController implements ReactiveServiceCrudController getProductConfigMetadataByAccessId(@PathVariable @Parameter(description = "产品ID") String id, + @PathVariable + @Parameter(description = "接入方式ID") String accessId) { + return configMetadataManager.getProductConfigMetadataByAccessId(id, accessId); + } + + @GetMapping("/{id:.+}/config-metadata/{metadataType}/{metadataId}/{typeId}") @QueryAction @Operation(summary = "获取产品物模型的拓展配置定义") -- Gitee From 32a3452f7b2bccdb8b6566af167e451e4037e6eb Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 20 Apr 2023 10:09:58 +0800 Subject: [PATCH 39/50] feat(maven): 2.1.0-SNAPSHOT --- jetlinks-components/common-component/pom.xml | 2 +- jetlinks-components/configure-component/pom.xml | 2 +- jetlinks-components/dashboard-component/pom.xml | 2 +- jetlinks-components/elasticsearch-component/pom.xml | 2 +- jetlinks-components/gateway-component/pom.xml | 2 +- jetlinks-components/io-component/pom.xml | 2 +- jetlinks-components/logging-component/pom.xml | 2 +- jetlinks-components/network-component/http-component/pom.xml | 2 +- jetlinks-components/network-component/mqtt-component/pom.xml | 2 +- jetlinks-components/network-component/network-core/pom.xml | 2 +- jetlinks-components/network-component/pom.xml | 2 +- jetlinks-components/network-component/tcp-component/pom.xml | 2 +- jetlinks-components/notify-component/notify-core/pom.xml | 2 +- jetlinks-components/notify-component/notify-dingtalk/pom.xml | 2 +- jetlinks-components/notify-component/notify-email/pom.xml | 2 +- jetlinks-components/notify-component/notify-sms/pom.xml | 2 +- jetlinks-components/notify-component/notify-voice/pom.xml | 2 +- jetlinks-components/notify-component/notify-webhook/pom.xml | 2 +- jetlinks-components/notify-component/notify-wechat/pom.xml | 2 +- jetlinks-components/notify-component/pom.xml | 2 +- jetlinks-components/pom.xml | 2 +- jetlinks-components/protocol-component/pom.xml | 2 +- jetlinks-components/relation-component/pom.xml | 2 +- jetlinks-components/rule-engine-component/pom.xml | 2 +- jetlinks-components/script-component/pom.xml | 2 +- jetlinks-components/tdengine-component/pom.xml | 2 +- jetlinks-components/things-component/pom.xml | 2 +- jetlinks-components/timeseries-component/pom.xml | 2 +- jetlinks-manager/authentication-manager/pom.xml | 2 +- jetlinks-manager/device-manager/pom.xml | 2 +- jetlinks-manager/logging-manager/pom.xml | 2 +- jetlinks-manager/network-manager/pom.xml | 2 +- jetlinks-manager/notify-manager/pom.xml | 2 +- jetlinks-manager/pom.xml | 2 +- jetlinks-manager/rule-engine-manager/pom.xml | 2 +- jetlinks-standalone/pom.xml | 2 +- pom.xml | 2 +- 37 files changed, 37 insertions(+), 37 deletions(-) diff --git a/jetlinks-components/common-component/pom.xml b/jetlinks-components/common-component/pom.xml index 2ccd8f5a..382f5bdf 100644 --- a/jetlinks-components/common-component/pom.xml +++ b/jetlinks-components/common-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/configure-component/pom.xml b/jetlinks-components/configure-component/pom.xml index 284b6dbf..56c66142 100644 --- a/jetlinks-components/configure-component/pom.xml +++ b/jetlinks-components/configure-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/dashboard-component/pom.xml b/jetlinks-components/dashboard-component/pom.xml index fa7b79c7..5512c817 100644 --- a/jetlinks-components/dashboard-component/pom.xml +++ b/jetlinks-components/dashboard-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/elasticsearch-component/pom.xml b/jetlinks-components/elasticsearch-component/pom.xml index afb41ec6..90add651 100644 --- a/jetlinks-components/elasticsearch-component/pom.xml +++ b/jetlinks-components/elasticsearch-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/gateway-component/pom.xml b/jetlinks-components/gateway-component/pom.xml index 67e337ca..5588e1b1 100644 --- a/jetlinks-components/gateway-component/pom.xml +++ b/jetlinks-components/gateway-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/io-component/pom.xml b/jetlinks-components/io-component/pom.xml index 544a5f46..1a7cf4f2 100644 --- a/jetlinks-components/io-component/pom.xml +++ b/jetlinks-components/io-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/logging-component/pom.xml b/jetlinks-components/logging-component/pom.xml index 770daf67..84531f2e 100644 --- a/jetlinks-components/logging-component/pom.xml +++ b/jetlinks-components/logging-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/network-component/http-component/pom.xml b/jetlinks-components/network-component/http-component/pom.xml index d895e982..474df1e3 100755 --- a/jetlinks-components/network-component/http-component/pom.xml +++ b/jetlinks-components/network-component/http-component/pom.xml @@ -5,7 +5,7 @@ network-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/network-component/mqtt-component/pom.xml b/jetlinks-components/network-component/mqtt-component/pom.xml index 79bf6707..705e9360 100644 --- a/jetlinks-components/network-component/mqtt-component/pom.xml +++ b/jetlinks-components/network-component/mqtt-component/pom.xml @@ -5,7 +5,7 @@ network-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/network-component/network-core/pom.xml b/jetlinks-components/network-component/network-core/pom.xml index 5de7cc2d..fe2348b5 100644 --- a/jetlinks-components/network-component/network-core/pom.xml +++ b/jetlinks-components/network-component/network-core/pom.xml @@ -3,7 +3,7 @@ network-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/network-component/pom.xml b/jetlinks-components/network-component/pom.xml index bc41d114..6ca2c2b7 100644 --- a/jetlinks-components/network-component/pom.xml +++ b/jetlinks-components/network-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml pom diff --git a/jetlinks-components/network-component/tcp-component/pom.xml b/jetlinks-components/network-component/tcp-component/pom.xml index 2ba5123c..8e2b8d4b 100644 --- a/jetlinks-components/network-component/tcp-component/pom.xml +++ b/jetlinks-components/network-component/tcp-component/pom.xml @@ -5,7 +5,7 @@ network-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/notify-component/notify-core/pom.xml b/jetlinks-components/notify-component/notify-core/pom.xml index aff5535c..c44ecfa1 100755 --- a/jetlinks-components/notify-component/notify-core/pom.xml +++ b/jetlinks-components/notify-component/notify-core/pom.xml @@ -5,7 +5,7 @@ notify-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/notify-component/notify-dingtalk/pom.xml b/jetlinks-components/notify-component/notify-dingtalk/pom.xml index d6e43cf8..9ce8cd9b 100755 --- a/jetlinks-components/notify-component/notify-dingtalk/pom.xml +++ b/jetlinks-components/notify-component/notify-dingtalk/pom.xml @@ -5,7 +5,7 @@ notify-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/notify-component/notify-email/pom.xml b/jetlinks-components/notify-component/notify-email/pom.xml index 2d70752d..f238072c 100755 --- a/jetlinks-components/notify-component/notify-email/pom.xml +++ b/jetlinks-components/notify-component/notify-email/pom.xml @@ -5,7 +5,7 @@ notify-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/notify-component/notify-sms/pom.xml b/jetlinks-components/notify-component/notify-sms/pom.xml index 22f4d35d..49950cc0 100755 --- a/jetlinks-components/notify-component/notify-sms/pom.xml +++ b/jetlinks-components/notify-component/notify-sms/pom.xml @@ -5,7 +5,7 @@ notify-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/notify-component/notify-voice/pom.xml b/jetlinks-components/notify-component/notify-voice/pom.xml index 6b0941e3..8d456739 100644 --- a/jetlinks-components/notify-component/notify-voice/pom.xml +++ b/jetlinks-components/notify-component/notify-voice/pom.xml @@ -5,7 +5,7 @@ notify-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/notify-component/notify-webhook/pom.xml b/jetlinks-components/notify-component/notify-webhook/pom.xml index da2dea6e..61e53bed 100644 --- a/jetlinks-components/notify-component/notify-webhook/pom.xml +++ b/jetlinks-components/notify-component/notify-webhook/pom.xml @@ -5,7 +5,7 @@ notify-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/notify-component/notify-wechat/pom.xml b/jetlinks-components/notify-component/notify-wechat/pom.xml index 0bc3536a..fd500db2 100755 --- a/jetlinks-components/notify-component/notify-wechat/pom.xml +++ b/jetlinks-components/notify-component/notify-wechat/pom.xml @@ -5,7 +5,7 @@ notify-component org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/notify-component/pom.xml b/jetlinks-components/notify-component/pom.xml index d397371b..627bb3f8 100644 --- a/jetlinks-components/notify-component/pom.xml +++ b/jetlinks-components/notify-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/pom.xml b/jetlinks-components/pom.xml index a78e51fc..dff782ac 100644 --- a/jetlinks-components/pom.xml +++ b/jetlinks-components/pom.xml @@ -5,7 +5,7 @@ jetlinks-community org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/protocol-component/pom.xml b/jetlinks-components/protocol-component/pom.xml index 22870134..205cf5ba 100755 --- a/jetlinks-components/protocol-component/pom.xml +++ b/jetlinks-components/protocol-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/relation-component/pom.xml b/jetlinks-components/relation-component/pom.xml index 3dfb4d6e..90c097f6 100644 --- a/jetlinks-components/relation-component/pom.xml +++ b/jetlinks-components/relation-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/rule-engine-component/pom.xml b/jetlinks-components/rule-engine-component/pom.xml index 6d429a6e..9688ed94 100644 --- a/jetlinks-components/rule-engine-component/pom.xml +++ b/jetlinks-components/rule-engine-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/script-component/pom.xml b/jetlinks-components/script-component/pom.xml index 512f45fb..74b7129b 100644 --- a/jetlinks-components/script-component/pom.xml +++ b/jetlinks-components/script-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/tdengine-component/pom.xml b/jetlinks-components/tdengine-component/pom.xml index 56ee37f6..c727a5d3 100755 --- a/jetlinks-components/tdengine-component/pom.xml +++ b/jetlinks-components/tdengine-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-components/things-component/pom.xml b/jetlinks-components/things-component/pom.xml index 447b6684..cc16e82e 100644 --- a/jetlinks-components/things-component/pom.xml +++ b/jetlinks-components/things-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT 4.0.0 diff --git a/jetlinks-components/timeseries-component/pom.xml b/jetlinks-components/timeseries-component/pom.xml index f33976c7..cc231508 100644 --- a/jetlinks-components/timeseries-component/pom.xml +++ b/jetlinks-components/timeseries-component/pom.xml @@ -5,7 +5,7 @@ jetlinks-components org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/jetlinks-manager/authentication-manager/pom.xml b/jetlinks-manager/authentication-manager/pom.xml index 0275f6c7..96758fe8 100644 --- a/jetlinks-manager/authentication-manager/pom.xml +++ b/jetlinks-manager/authentication-manager/pom.xml @@ -7,7 +7,7 @@ org.jetlinks.community jetlinks-manager - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml authentication-manager diff --git a/jetlinks-manager/device-manager/pom.xml b/jetlinks-manager/device-manager/pom.xml index c97d9877..25f06d8b 100644 --- a/jetlinks-manager/device-manager/pom.xml +++ b/jetlinks-manager/device-manager/pom.xml @@ -7,7 +7,7 @@ org.jetlinks.community jetlinks-manager - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml device-manager diff --git a/jetlinks-manager/logging-manager/pom.xml b/jetlinks-manager/logging-manager/pom.xml index 217c16f5..96dd7098 100644 --- a/jetlinks-manager/logging-manager/pom.xml +++ b/jetlinks-manager/logging-manager/pom.xml @@ -7,7 +7,7 @@ org.jetlinks.community jetlinks-manager - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT logging-manager diff --git a/jetlinks-manager/network-manager/pom.xml b/jetlinks-manager/network-manager/pom.xml index 55dec7ad..f569fcb7 100644 --- a/jetlinks-manager/network-manager/pom.xml +++ b/jetlinks-manager/network-manager/pom.xml @@ -7,7 +7,7 @@ org.jetlinks.community jetlinks-manager - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml network-manager diff --git a/jetlinks-manager/notify-manager/pom.xml b/jetlinks-manager/notify-manager/pom.xml index ea5acd85..d9ba177d 100644 --- a/jetlinks-manager/notify-manager/pom.xml +++ b/jetlinks-manager/notify-manager/pom.xml @@ -7,7 +7,7 @@ org.jetlinks.community jetlinks-manager - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml notify-manager diff --git a/jetlinks-manager/pom.xml b/jetlinks-manager/pom.xml index 056beac9..097babc7 100644 --- a/jetlinks-manager/pom.xml +++ b/jetlinks-manager/pom.xml @@ -5,7 +5,7 @@ jetlinks-community org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT pom 4.0.0 diff --git a/jetlinks-manager/rule-engine-manager/pom.xml b/jetlinks-manager/rule-engine-manager/pom.xml index 9d152bac..e8950779 100644 --- a/jetlinks-manager/rule-engine-manager/pom.xml +++ b/jetlinks-manager/rule-engine-manager/pom.xml @@ -7,7 +7,7 @@ org.jetlinks.community jetlinks-manager - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml rule-engine-manager diff --git a/jetlinks-standalone/pom.xml b/jetlinks-standalone/pom.xml index b88a66f5..bf997c79 100644 --- a/jetlinks-standalone/pom.xml +++ b/jetlinks-standalone/pom.xml @@ -5,7 +5,7 @@ jetlinks-community org.jetlinks.community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 72ffe9ac..9d1027c2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.jetlinks.community jetlinks-community - 2.0.0-SNAPSHOT + 2.1.0-SNAPSHOT jetlinks-components jetlinks-manager -- Gitee From 3f4297ed0685d560d9fd9debcc7e56dab0339484 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 20 Apr 2023 10:10:23 +0800 Subject: [PATCH 40/50] =?UTF-8?q?refactor(=E5=9F=BA=E7=A1=80=E6=A8=A1?= =?UTF-8?q?=E5=9D=97):=20=E4=BC=98=E5=8C=96=E5=8D=8F=E8=AE=AE=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/protocol/LazyInitManagementProtocolSupports.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetlinks-components/protocol-component/src/main/java/org/jetlinks/community/protocol/LazyInitManagementProtocolSupports.java b/jetlinks-components/protocol-component/src/main/java/org/jetlinks/community/protocol/LazyInitManagementProtocolSupports.java index 9fd62700..81568465 100755 --- a/jetlinks-components/protocol-component/src/main/java/org/jetlinks/community/protocol/LazyInitManagementProtocolSupports.java +++ b/jetlinks-components/protocol-component/src/main/java/org/jetlinks/community/protocol/LazyInitManagementProtocolSupports.java @@ -79,7 +79,7 @@ public class LazyInitManagementProtocolSupports extends StaticProtocolSupports i consumer.accept(e); }) .onErrorResume((e) -> { - log.error("{} protocol[{}] error: {}", operation, definition.getId(), e); + log.error("{} protocol[{}] error: {}", operation, definition.getId(), e.getLocalizedMessage()); return Mono.empty(); }) .then(); -- Gitee From c145abb6b3046870b27bee2d2dd9de7189e50a33 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 20 Apr 2023 10:15:30 +0800 Subject: [PATCH 41/50] =?UTF-8?q?refactor(maven):=20=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notify-component/notify-sms/pom.xml | 1 - .../notify-component/notify-voice/pom.xml | 1 - pom.xml | 31 +++++++++++++------ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/jetlinks-components/notify-component/notify-sms/pom.xml b/jetlinks-components/notify-component/notify-sms/pom.xml index 49950cc0..2cb8554e 100755 --- a/jetlinks-components/notify-component/notify-sms/pom.xml +++ b/jetlinks-components/notify-component/notify-sms/pom.xml @@ -20,7 +20,6 @@ com.aliyun aliyun-java-sdk-core - 4.5.2 diff --git a/jetlinks-components/notify-component/notify-voice/pom.xml b/jetlinks-components/notify-component/notify-voice/pom.xml index 8d456739..11f45d3c 100644 --- a/jetlinks-components/notify-component/notify-voice/pom.xml +++ b/jetlinks-components/notify-component/notify-voice/pom.xml @@ -15,7 +15,6 @@ com.aliyun aliyun-java-sdk-core - 4.5.2 ${project.groupId} diff --git a/pom.xml b/pom.xml index 9d1027c2..bec382d9 100644 --- a/pom.xml +++ b/pom.xml @@ -19,26 +19,30 @@ 2.7.3 1.8 ${java.version} - 4.0.15 - 4.1.0 - 3.0.2 - 1.2.0 + + 4.0.16-SNAPSHOT + 4.1.1-SNAPSHOT + 1.2.1-SNAPSHOT + 1.0.4 + 1.0.16-SNAPSHOT + + Borca-SR2 - 4.1.82.Final + 3.0.2 + 4.1.89.Final 7.17.5 - 1.0.4 - 1.0.15 3.7.0 1.2.83 2020.0.22 - 4.3.3 + 4.3.7 2.18.0 1.2.11 1.6.11 - 2.13.4 + 2.13.5 1.17.0 - 2.2.2 + 2.2.8 5.12.1 + 4.5.2 @@ -461,6 +465,13 @@ 1.10.0 + + com.aliyun + aliyun-java-sdk-core + ${aliyun.sdk.core} + + + -- Gitee From b89aa1138a6f43dd94bd6b52a4c75b60815350dc Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 20 Apr 2023 10:15:48 +0800 Subject: [PATCH 42/50] =?UTF-8?q?refactor(maven):=20=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bec382d9..024d1b92 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ UTF-8 zh_CN - 2.7.3 + 2.7.10 1.8 ${java.version} -- Gitee From 7eb601b84942f937216c3c7c1466ee569c4de562 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 20 Apr 2023 10:25:08 +0800 Subject: [PATCH 43/50] =?UTF-8?q?refactor(maven):=20=E5=8D=87=E7=BA=A7reac?= =?UTF-8?q?tor=202020.0.31?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 024d1b92..769735fa 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 7.17.5 3.7.0 1.2.83 - 2020.0.22 + 2020.0.31 4.3.7 2.18.0 1.2.11 -- Gitee From d51aa6ac1faca05f021fdf3c0efef245f16e4a11 Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Fri, 21 Apr 2023 18:22:35 +0800 Subject: [PATCH 44/50] =?UTF-8?q?fix(=E7=BD=91=E7=BB=9C=E7=BB=84=E4=BB=B6)?= =?UTF-8?q?:=20=E8=AE=BE=E7=BD=AE=E6=94=AF=E6=8C=81=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E7=B1=BB=E5=9E=8B=E7=9A=84=E7=BD=91=E7=BB=9C?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E5=8F=AF=E4=BB=A5=E8=A2=AB=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=20(#273)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/http/server/vertx/DefaultHttpServerProvider.java | 5 +++++ .../community/network/mqtt/client/MqttClientProvider.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/jetlinks-components/network-component/http-component/src/main/java/org/jetlinks/community/network/http/server/vertx/DefaultHttpServerProvider.java b/jetlinks-components/network-component/http-component/src/main/java/org/jetlinks/community/network/http/server/vertx/DefaultHttpServerProvider.java index cb5f2e30..fea24632 100755 --- a/jetlinks-components/network-component/http-component/src/main/java/org/jetlinks/community/network/http/server/vertx/DefaultHttpServerProvider.java +++ b/jetlinks-components/network-component/http-component/src/main/java/org/jetlinks/community/network/http/server/vertx/DefaultHttpServerProvider.java @@ -140,4 +140,9 @@ public class DefaultHttpServerProvider implements NetworkProvider } return Mono.just(options); } + + @Override + public boolean isReusable() { + return true; + } } -- Gitee From 6a2035fee6d54bb9a9b416130e4deeb3f667812a Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Fri, 21 Apr 2023 20:20:37 +0800 Subject: [PATCH 45/50] =?UTF-8?q?feat(=E9=80=9A=E7=9F=A5=E8=AE=A2=E9=98=85?= =?UTF-8?q?):=20=E6=94=AF=E6=8C=81=E5=91=8A=E8=AD=A6=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E7=AB=99=E5=86=85=E4=BF=A1=E9=80=9A=E7=9F=A5=20(#274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notify/manager/entity/Notification.java | 11 ++ .../manager/entity/NotificationEntity.java | 22 ++- .../manager/entity/NotifyChannelEntity.java | 87 +++++++++ .../entity/NotifySubscriberEntity.java | 19 ++ .../manager/enums/NotifyChannelState.java | 19 ++ .../service/NotifySubscriberService.java | 139 +++++++++----- .../notify/manager/subscriber/Subscriber.java | 9 +- .../subscriber/SubscriberProviders.java | 25 +++ .../channel/InsideMailChannelProvider.java | 61 +++++++ .../channel/NotificationDispatcher.java | 172 ++++++++++++++++++ .../subscriber/channel/NotifyChannel.java | 17 ++ .../channel/NotifyChannelProvider.java | 16 ++ .../subscriber/providers/AlarmProvider.java | 24 ++- 13 files changed, 567 insertions(+), 54 deletions(-) create mode 100644 jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifyChannelEntity.java create mode 100644 jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/enums/NotifyChannelState.java create mode 100644 jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/SubscriberProviders.java create mode 100644 jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/InsideMailChannelProvider.java create mode 100644 jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotificationDispatcher.java create mode 100644 jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannel.java create mode 100644 jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannelProvider.java diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/Notification.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/Notification.java index 88e5e54a..9df48de7 100644 --- a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/Notification.java +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/Notification.java @@ -7,6 +7,7 @@ import org.hswebframework.web.id.IDGenerator; import org.jetlinks.community.notify.manager.subscriber.Notify; import java.io.Serializable; +import java.util.List; @Getter @Setter @@ -27,10 +28,17 @@ public class Notification implements Serializable { private String message; + + private Object detail; + + private String code; + private String dataId; private long notifyTime; + private List notifyChannels; + public static Notification from(NotifySubscriberEntity entity) { Notification notification = new Notification(); @@ -39,6 +47,7 @@ public class Notification implements Serializable { notification.subscriber = entity.getSubscriber(); notification.topicName = entity.getTopicName(); notification.setTopicProvider(entity.getTopicProvider()); + notification.setNotifyChannels(entity.getNotifyChannels()); return notification; } @@ -49,6 +58,8 @@ public class Notification implements Serializable { target.setMessage(message.getMessage()); target.setDataId(message.getDataId()); target.setNotifyTime(message.getNotifyTime()); + target.setDetail(message.getDetail()); + target.setCode(message.getCode()); return target; } diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotificationEntity.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotificationEntity.java index 731aaa9d..62cc0375 100644 --- a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotificationEntity.java +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotificationEntity.java @@ -4,12 +4,14 @@ import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; +import lombok.SneakyThrows; import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType; 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.bean.FastBeanCopier; import org.jetlinks.community.notify.manager.enums.NotificationState; +import org.jetlinks.community.utils.ObjectMappers; import javax.persistence.Column; import javax.persistence.Index; @@ -58,6 +60,16 @@ public class NotificationEntity extends GenericEntity { @Schema(description = "通知时间") private Long notifyTime; + @Column(length = 128) + @Schema(description = "通知编码") + private String code; + + @Column + @Schema(description = "详情") + @ColumnType(jdbcType = JDBCType.CLOB, javaType = String.class) + private String detailJson; + + @Column(length = 32) @EnumCodec @DefaultValue("unread") @@ -69,7 +81,15 @@ public class NotificationEntity extends GenericEntity { @Schema(description = "说明") private String description; + @SneakyThrows public static NotificationEntity from(Notification notification) { - return FastBeanCopier.copy(notification, new NotificationEntity()); + NotificationEntity entity = FastBeanCopier.copy(notification, new NotificationEntity()); + Object detail = notification.getDetail(); + + entity.setCode(notification.getCode()); + if (detail != null) { + entity.setDetailJson(ObjectMappers.JSON_MAPPER.writeValueAsString(detail)); + } + return entity; } } diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifyChannelEntity.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifyChannelEntity.java new file mode 100644 index 00000000..eb3dc492 --- /dev/null +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifyChannelEntity.java @@ -0,0 +1,87 @@ +package org.jetlinks.community.notify.manager.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType; +import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue; +import org.hswebframework.ezorm.rdb.mapping.annotation.EnumCodec; +import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec; +import org.hswebframework.web.api.crud.entity.GenericEntity; +import org.hswebframework.web.validator.CreateGroup; +//import org.jetlinks.community.authorize.AuthenticationSpec; +import org.jetlinks.community.notify.manager.enums.NotifyChannelState; +import org.jetlinks.community.notify.manager.subscriber.SubscriberProvider; +import org.jetlinks.community.notify.manager.subscriber.channel.NotifyChannelProvider; + +import javax.persistence.Column; +import javax.persistence.Table; +import javax.validation.constraints.NotBlank; +import java.sql.JDBCType; +import java.util.Map; + +/** + * 通知通道(配置). + * 用于定义哪些权限范围(grant),哪种主题(topicProvider),支持何种方式(channel)进行通知 + *

+ * 比如: 管理员角色的用户可以使用邮件通知,但是普通用户只能使用站内信通知. + * + * @author zhouhao + * @since 2.0 + */ +@Table(name = "notify_channel") +@Getter +@Setter +@Schema(description = "通知通道(配置)") +public class NotifyChannelEntity extends GenericEntity { + + @Column(nullable = false, length = 32) + @NotBlank(groups = CreateGroup.class) + @Schema(description = "名称") + private String name; + +// @Column +// @JsonCodec +// @ColumnType(jdbcType = JDBCType.LONGVARCHAR, javaType = String.class) +// @Schema(description = "权限范围") +// private AuthenticationSpec grant; + + /** + * @see SubscriberProvider#getId() + */ + @Column(nullable = false, length = 32, updatable = false) + @NotBlank(groups = CreateGroup.class) + @Schema(description = "主题提供商标识") + private String topicProvider; + + @Column(nullable = false, length = 32) + @NotBlank(groups = CreateGroup.class) + @Schema(description = "主题提供商名称") + private String topicName; + + /** + * @see NotifyChannelProvider#getId() + */ + @Column(nullable = false, length = 32, updatable = false) + @NotBlank(groups = CreateGroup.class) + @Schema(description = "通知类型") + private String channelProvider; + + /** + * @see NotifyChannelProvider#createChannel(Map) + * @see org.jetlinks.community.notify.manager.subscriber.channel.notifiers.NotifierChannelProvider.NotifyChannelConfig + */ + @Column + @JsonCodec + @ColumnType(jdbcType = JDBCType.LONGVARCHAR, javaType = String.class) + @Schema(description = "通知配置") + private Map channelConfiguration; + + @Column(length = 32) + @EnumCodec + @ColumnType(javaType = String.class) + @DefaultValue("enabled") + @Schema(description = "状态") + private NotifyChannelState state; + +} diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifySubscriberEntity.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifySubscriberEntity.java index fc1507c3..a35a43e3 100644 --- a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifySubscriberEntity.java +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/entity/NotifySubscriberEntity.java @@ -12,6 +12,8 @@ import org.jetlinks.community.notify.manager.enums.SubscribeState; import javax.persistence.Column; import javax.persistence.Index; import javax.persistence.Table; +import java.util.List; +import java.util.Locale; import java.util.Map; /** @@ -75,5 +77,22 @@ public class NotifySubscriberEntity extends GenericEntity { @Schema(description = "状态.") private SubscribeState state; + @Column(length = 32) + @Schema(description = "订阅语言") + private String locale; + + + /** + * @see NotifyChannelEntity#getId() + */ + @Column(length = 3000) + @Schema(description = "通知方式") + @JsonCodec + @ColumnType(javaType = String.class) + private List notifyChannels; + + public Locale toLocale() { + return locale == null ? Locale.getDefault() : Locale.forLanguageTag(locale); + } } diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/enums/NotifyChannelState.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/enums/NotifyChannelState.java new file mode 100644 index 00000000..d158f356 --- /dev/null +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/enums/NotifyChannelState.java @@ -0,0 +1,19 @@ +package org.jetlinks.community.notify.manager.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.hswebframework.web.dict.EnumDict; + +@Getter +@AllArgsConstructor +public enum NotifyChannelState implements EnumDict { + enabled("正常"), + disabled("禁用"); + + private final String text; + + @Override + public String getValue() { + return name(); + } +} diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/service/NotifySubscriberService.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/service/NotifySubscriberService.java index 7c0a9ba4..35fd9d10 100644 --- a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/service/NotifySubscriberService.java +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/service/NotifySubscriberService.java @@ -1,23 +1,28 @@ package org.jetlinks.community.notify.manager.service; + import lombok.extern.slf4j.Slf4j; import org.hswebframework.web.authorization.ReactiveAuthenticationHolder; -import org.hswebframework.web.crud.events.EntityCreatedEvent; -import org.hswebframework.web.crud.events.EntityDeletedEvent; -import org.hswebframework.web.crud.events.EntityModifyEvent; -import org.hswebframework.web.crud.events.EntitySavedEvent; +import org.hswebframework.web.crud.events.*; import org.hswebframework.web.crud.service.GenericReactiveCrudService; +import org.hswebframework.web.exception.BusinessException; +import org.hswebframework.web.i18n.LocaleUtils; +import org.jetlinks.core.cluster.ClusterManager; +import org.jetlinks.core.event.EventBus; +import org.jetlinks.community.gateway.annotation.Subscribe; import org.jetlinks.community.notify.manager.entity.Notification; import org.jetlinks.community.notify.manager.entity.NotifySubscriberEntity; import org.jetlinks.community.notify.manager.enums.SubscribeState; import org.jetlinks.community.notify.manager.subscriber.SubscriberProvider; -import org.jetlinks.core.cluster.ClusterManager; -import org.jetlinks.core.event.EventBus; +import org.jetlinks.community.notify.manager.subscriber.SubscriberProviders; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.CommandLineRunner; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import reactor.core.Disposable; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.List; @@ -31,19 +36,20 @@ public class NotifySubscriberService extends GenericReactiveCrudService providers = new ConcurrentHashMap<>(); private final Map subscribers = new ConcurrentHashMap<>(); + private final ApplicationEventPublisher eventPublisher; + public NotifySubscriberService(EventBus eventBus, - ClusterManager clusterManager, - List providers) { + ObjectProvider providers, + ApplicationEventPublisher eventPublisher) { this.eventBus = eventBus; - this.clusterManager = clusterManager; + this.eventPublisher=eventPublisher; for (SubscriberProvider provider : providers) { this.providers.put(provider.getId(), provider); + SubscriberProviders.register(provider); } } @@ -51,69 +57,109 @@ public class NotifySubscriberService extends GenericReactiveCrudServicegetTopic("notification-changed") - .subscribe() - .subscribe(this::handleSubscribe); + protected Mono doNotifyChange(NotifySubscriberEntity entity) { + return eventBus + .publish("/notification-changed", entity) + .then(); + } - protected void doNotifyChange(NotifySubscriberEntity entity) { - clusterManager.getTopic("notification-changed") - .publish(Mono.just(entity)) - .retry(3) - .subscribe(); + @EventListener + public void handleEvent(EntityPrepareCreateEvent entity) { + //填充语言 + entity.async( + LocaleUtils + .currentReactive() + .doOnNext(locale -> { + for (NotifySubscriberEntity subscriber : entity.getEntity()) { + if (subscriber.getLocale() == null) { + subscriber.setLocale(locale.toLanguageTag()); + } + } + }) + ); + } + + @EventListener + public void handleEvent(EntityPrepareSaveEvent entity) { + //填充语言 + entity.async( + LocaleUtils + .currentReactive() + .doOnNext(locale -> { + for (NotifySubscriberEntity subscriber : entity.getEntity()) { + if (subscriber.getLocale() == null) { + subscriber.setLocale(locale.toLanguageTag()); + } + } + }) + ); } @EventListener public void handleEvent(EntityCreatedEvent entity) { - entity.getEntity().forEach(this::doNotifyChange); + entity.async( + Flux.fromIterable(entity.getEntity()) + .flatMap(this::doNotifyChange) + ); } @EventListener public void handleEvent(EntitySavedEvent entity) { - entity.getEntity().forEach(this::doNotifyChange); + entity.async( + Flux.fromIterable(entity.getEntity()) + .flatMap(this::doNotifyChange) + ); } @EventListener public void handleEvent(EntityDeletedEvent entity) { - entity.getEntity().forEach(e -> { - e.setState(SubscribeState.disabled); - doNotifyChange(e); - }); + entity.async( + Flux.fromIterable(entity.getEntity()) + .doOnNext(e -> e.setState(SubscribeState.disabled)) + .flatMap(this::doNotifyChange) + ); + } @EventListener public void handleEvent(EntityModifyEvent entity) { - entity.getAfter().forEach(this::doNotifyChange); + entity.async( + Flux.fromIterable(entity.getAfter()) + .flatMap(this::doNotifyChange) + ); } - private void handleSubscribe(NotifySubscriberEntity entity) { + @Subscribe("/notification-changed") + public void handleSubscribe(NotifySubscriberEntity entity) { //取消订阅 if (entity.getState() == SubscribeState.disabled) { Optional.ofNullable(subscribers.remove(entity.getId())) - .ifPresent(Disposable::dispose); + .ifPresent(Disposable::dispose); log.debug("unsubscribe:{}({}),{}", entity.getTopicProvider(), entity.getTopicName(), entity.getId()); return; } //模版 Notification template = Notification.from(entity); - //转发通知 - String dispatch = template.createTopic(); Disposable old = subscribers .put(entity.getId(), - Mono.zip(ReactiveAuthenticationHolder.get(entity.getSubscriber()), Mono.justOrEmpty(getProvider(entity.getTopicProvider()))) - .flatMap(tp2 -> tp2.getT2().createSubscriber(entity.getId(),tp2.getT1(), entity.getTopicConfig())) - .flatMap(subscriber -> - subscriber - .subscribe() - .map(template::copyWithMessage) - .flatMap(notification -> eventBus.publish(dispatch, notification)) - .onErrorContinue((err, obj) -> log.error(err.getMessage(), err)) - .then()) - .subscribe() + Mono + .zip(ReactiveAuthenticationHolder.get(entity.getSubscriber()), Mono.justOrEmpty(getProvider(entity.getTopicProvider()))) + .flatMap(tp2 -> tp2.getT2().createSubscriber(entity.getId(), tp2.getT1(), entity.getTopicConfig())) + .flatMap(subscriber -> + subscriber + .subscribe(entity.toLocale()) + .map(template::copyWithMessage) + .doOnNext(eventPublisher::publishEvent) + .onErrorResume((err) -> { + log.error(err.getMessage(), err); + return Mono.empty(); + }) + .then()) + .subscribe() ); log.debug("subscribe :{}({})", template.getTopicProvider(), template.getTopicName()); @@ -124,8 +170,9 @@ public class NotifySubscriberService extends GenericReactiveCrudService doSubscribe(NotifySubscriberEntity entity) { - return Mono.justOrEmpty(getProvider(entity.getTopicProvider())) - .switchIfEmpty(Mono.error(() -> new IllegalArgumentException("不支持的主题:" + entity.getTopicProvider()))) + return Mono + .justOrEmpty(getProvider(entity.getTopicProvider())) + .switchIfEmpty(Mono.error(() -> new BusinessException("error.unsupported_topics", 500, entity.getTopicProvider()))) .map(provider -> { entity.setTopicName(provider.getName()); return entity; @@ -133,9 +180,10 @@ public class NotifySubscriberService extends GenericReactiveCrudService { if (StringUtils.isEmpty(entity.getId())) { entity.setId(null); - return save(Mono.just(entity)); + return save(entity); } else { - return createUpdate().set(entity) + return createUpdate() + .set(entity) .where(NotifySubscriberEntity::getId, entity.getId()) .and(NotifySubscriberEntity::getSubscriberType, entity.getSubscriberType()) .and(NotifySubscriberEntity::getSubscriber, entity.getSubscriber()) @@ -147,7 +195,6 @@ public class NotifySubscriberService extends GenericReactiveCrudService subscribe(); + Flux subscribe(Locale locale); + + default Flux subscribe() { + return subscribe(Locale.getDefault()); + } + } diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/SubscriberProviders.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/SubscriberProviders.java new file mode 100644 index 00000000..eb23bbb4 --- /dev/null +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/SubscriberProviders.java @@ -0,0 +1,25 @@ +package org.jetlinks.community.notify.manager.subscriber; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public class SubscriberProviders { + + private final static Map providers = new ConcurrentHashMap<>(); + + + public static void register(SubscriberProvider provider) { + providers.put(provider.getId(), provider); + } + + public static List getProviders() { + return new ArrayList<>(providers.values()); + } + + public static Optional getProvider(String id) { + return Optional.ofNullable(providers.get(id)); + } +} diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/InsideMailChannelProvider.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/InsideMailChannelProvider.java new file mode 100644 index 00000000..03acafee --- /dev/null +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/InsideMailChannelProvider.java @@ -0,0 +1,61 @@ +package org.jetlinks.community.notify.manager.subscriber.channel; + +import lombok.AllArgsConstructor; +import org.jetlinks.community.notify.manager.entity.Notification; +import org.jetlinks.core.event.EventBus; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.Map; + +/** + * 站内信通知,通过推送通知信息到事件总线. + *

+ * 由{@link org.jetlinks.community.notify.manager.message.NotificationsPublishProvider}推送到前端. + *

+ * 由{@link org.jetlinks.community.notify.manager.service.NotificationService}写入到数据库. + * + * @author zhouhao + * @since 2.0 + */ +@Component +@AllArgsConstructor +public class InsideMailChannelProvider implements NotifyChannelProvider, NotifyChannel { + public static final String provider = "inside-mail"; + + private final EventBus eventBus; + + @Override + public String getId() { + return "inside-mail"; + } + + @Override + public String getName() { + return "站内信"; + } + + @Override + public Mono createChannel(Map configuration) { + return Mono.just(this); + } + + @Override + public Mono sendNotify(Notification notification) { + //设置了站内信的订阅才推送的事件总线 + return eventBus + .publish(notification.createTopic(), notification) + .then(); + } + + @Override + public void dispose() { + + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } +} diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotificationDispatcher.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotificationDispatcher.java new file mode 100644 index 00000000..d11a277b --- /dev/null +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotificationDispatcher.java @@ -0,0 +1,172 @@ +package org.jetlinks.community.notify.manager.subscriber.channel; + +import lombok.extern.slf4j.Slf4j; +import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; +import org.hswebframework.web.crud.events.EntityCreatedEvent; +import org.hswebframework.web.crud.events.EntityDeletedEvent; +import org.hswebframework.web.crud.events.EntityModifyEvent; +import org.hswebframework.web.crud.events.EntitySavedEvent; +import org.jetlinks.community.gateway.annotation.Subscribe; +import org.jetlinks.community.notify.manager.entity.Notification; +import org.jetlinks.community.notify.manager.entity.NotifyChannelEntity; +import org.jetlinks.community.notify.manager.enums.NotifyChannelState; +import org.jetlinks.core.cache.ReactiveCacheContainer; +import org.jetlinks.core.event.EventBus; +import org.jetlinks.core.event.Subscription; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 通知订阅转发器,将通知信息转发到对应的订阅通道中 + * + * @author zhouhao + * @since 2.0 + */ +@Component +@Slf4j +public class NotificationDispatcher implements CommandLineRunner { + + private final EventBus eventBus; + + private final ReactiveCacheContainer channels = ReactiveCacheContainer.create(); + + private final Map providers = new HashMap<>(); + + private final ReactiveRepository channelRepository; + + public NotificationDispatcher(EventBus eventBus, + ObjectProvider providers, + ReactiveRepository channelRepository) { + this.eventBus = eventBus; + this.channelRepository = channelRepository; + //默认支持站内信 + this.channels.put(InsideMailChannelProvider.provider, new InsideMailChannelProvider(eventBus)); + + for (NotifyChannelProvider provider : providers) { + this.providers.put(provider.getId(), provider); + } + } + + @EventListener + public void handleNotifications(Notification notification) { + + List channelIdList = notification.getNotifyChannels(); + //默认站内信 + if (channelIdList == null) { + channelIdList = Collections.singletonList(InsideMailChannelProvider.provider); + } + //发送通知 + for (String notifyChannel : channelIdList) { + NotifyChannel dispatcher = channels.getNow(notifyChannel); + if (dispatcher != null) { + dispatcher + .sendNotify(notification) + .subscribe(); + } + } + + } + + @EventListener + public void handleEvent(EntityCreatedEvent event) { + + event.async( + register(event.getEntity()) + ); + } + + @EventListener + public void handleEvent(EntitySavedEvent event) { + + event.async( + register(event.getEntity()) + ); + } + + @EventListener + public void handleEvent(EntityModifyEvent event) { + + event.async( + register(event.getAfter()) + ); + } + + @EventListener + public void handleEvent(EntityDeletedEvent event) { + event.async( + unregister(event.getEntity()) + ); + } + + @Subscribe(value = "/_sys/notify-channel/unregister", features = Subscription.Feature.broker) + public void unregister(NotifyChannelEntity entity) { + channels.remove(entity.getId()); + } + + @Subscribe(value = "/_sys/notify-channel/register", features = Subscription.Feature.broker) + public Mono register(NotifyChannelEntity entity) { + if (entity.getState() == NotifyChannelState.disabled) { + channels.remove(entity.getId()); + } else { + return channels + .compute(entity.getId(), (ignore, old) -> { + if (null != old) { + old.dispose(); + } + return createChannel(entity); + }) + .then(); + } + return Mono.empty(); + } + + private Mono createChannel(NotifyChannelEntity entity) { + NotifyChannelProvider provider = providers.get(entity.getChannelProvider()); + if (null == provider) { + return Mono.empty(); + } + return provider.createChannel(entity.getChannelConfiguration()); + } + + private Mono unregister(List entities) { + for (NotifyChannelEntity entity : entities) { + unregister(entity); + } + return Flux.fromIterable(entities) + .flatMap(e -> eventBus.publish("/_sys/notify-channel/unregister", e)) + .then(); + } + + private Mono register(List entities) { + return Flux.fromIterable(entities) + .flatMap(e -> register(e) + .then(eventBus.publish("/_sys/notify-channel/register", e))) + .then(); + + } + + @Override + public void run(String... args) throws Exception { + channelRepository + .createQuery() + .where(NotifyChannelEntity::getState, NotifyChannelState.enabled) + .fetch() + .flatMap(e -> this + .register(e) + .onErrorResume(er -> { + log.warn("register notify channel error", er); + return Mono.empty(); + })) + .subscribe(); + + } +} diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannel.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannel.java new file mode 100644 index 00000000..70fdcf71 --- /dev/null +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannel.java @@ -0,0 +1,17 @@ +package org.jetlinks.community.notify.manager.subscriber.channel; + +import org.jetlinks.community.notify.manager.entity.Notification; +import reactor.core.Disposable; +import reactor.core.publisher.Mono; + +/** + * 订阅通知通道,用于发送通知信息 + * + * @author zhouhao + * @since 2.0 + */ +public interface NotifyChannel extends Disposable { + + Mono sendNotify(Notification notification); + +} diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannelProvider.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannelProvider.java new file mode 100644 index 00000000..477ef1ba --- /dev/null +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/channel/NotifyChannelProvider.java @@ -0,0 +1,16 @@ +package org.jetlinks.community.notify.manager.subscriber.channel; + +import org.springframework.core.Ordered; +import reactor.core.publisher.Mono; + +import java.util.Map; + +public interface NotifyChannelProvider extends Ordered { + + String getId(); + + String getName(); + + Mono createChannel(Map configuration); + +} diff --git a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/providers/AlarmProvider.java b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/providers/AlarmProvider.java index 458bced2..3455dbe5 100755 --- a/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/providers/AlarmProvider.java +++ b/jetlinks-manager/notify-manager/src/main/java/org/jetlinks/community/notify/manager/subscriber/providers/AlarmProvider.java @@ -3,6 +3,7 @@ package org.jetlinks.community.notify.manager.subscriber.providers; import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.hswebframework.web.authorization.Authentication; import org.hswebframework.web.i18n.LocaleUtils; import org.jetlinks.community.ValueObject; @@ -17,14 +18,20 @@ import org.jetlinks.core.metadata.DefaultConfigMetadata; import org.jetlinks.core.metadata.PropertyMetadata; import org.jetlinks.core.metadata.SimplePropertyMetadata; import org.jetlinks.core.metadata.types.StringType; +import org.jetlinks.core.utils.FluxUtils; import org.springframework.stereotype.Component; +import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.time.Duration; +import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.function.Consumer; @Component +@Slf4j public class AlarmProvider implements SubscriberProvider { private final EventBus eventBus; @@ -56,11 +63,15 @@ public class AlarmProvider implements SubscriberProvider { String alarmId = configs.getString("alarmConfigId").orElse("*"); String topic = Topics.alarm("*", "*", alarmId); - return Mono.justOrEmpty(()-> createSubscribe(id, new String[]{topic})); + + return Mono.just(locale -> createSubscribe(locale, id, new String[]{topic}) + //有效期内去重,防止同一个用户所在多个部门推送同一个告警 + .as(FluxUtils.distinct(Notify::getDataId, Duration.ofSeconds(10)))); } - private Flux createSubscribe(String id, + private Flux createSubscribe(Locale locale, + String id, String[] topics) { Subscription.Feature[] features = new Subscription.Feature[]{Subscription.Feature.local}; return Flux @@ -70,7 +81,7 @@ public class AlarmProvider implements SubscriberProvider { .map(msg -> { JSONObject json = msg.bodyToJson(); return Notify.of( - getNotifyMessage(json), + getNotifyMessage(locale, json), //告警记录ID json.getString("id"), System.currentTimeMillis(), @@ -80,18 +91,19 @@ public class AlarmProvider implements SubscriberProvider { })); } - private static String getNotifyMessage(JSONObject json) { + + private static String getNotifyMessage(Locale locale, JSONObject json) { String message; TargetType targetType = TargetType.of(json.getString("targetType")); String targetName = json.getString("targetName"); - String alarmName = json.getString("alarmName"); + String alarmName = json.getString("alarmConfigName"); if (targetType == TargetType.other) { message = String.format("[%s]发生告警:[%s]!", targetName, alarmName); } else { message = String.format("%s[%s]发生告警:[%s]!", targetType.getText(), targetName, alarmName); } - return LocaleUtils.resolveMessage("message.alarm.notify." + targetType.name(), message, targetName, alarmName); + return LocaleUtils.resolveMessage("message.alarm.notify." + targetType.name(), locale, message, targetName, alarmName); } @Override -- Gitee From fc5f9a5a25bd983d7d7b6b1b3bf262a5d629a155 Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Thu, 27 Apr 2023 16:24:25 +0800 Subject: [PATCH 46/50] =?UTF-8?q?fix(docker=E9=95=9C=E5=83=8F=E7=89=88?= =?UTF-8?q?=E6=9C=AC):=20=E4=BF=AE=E6=94=B9=E5=89=8D=E7=AB=AF=E9=95=9C?= =?UTF-8?q?=E5=83=8F=E7=89=88=E6=9C=AC=20(#278)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/run-all/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/run-all/docker-compose.yml b/docker/run-all/docker-compose.yml index 9595c05a..93d14101 100644 --- a/docker/run-all/docker-compose.yml +++ b/docker/run-all/docker-compose.yml @@ -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: -- Gitee From 309e5a57dcf4be3c3f235e11d001fec3a307ebe6 Mon Sep 17 00:00:00 2001 From: bestfeng1020 <31398465+bestfeng1020@users.noreply.github.com> Date: Thu, 4 May 2023 16:46:09 +0800 Subject: [PATCH 47/50] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E8=81=94=E5=8A=A8=E5=8F=91=E9=80=81=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91=E7=9F=AD=E4=BF=A1=E5=A4=B1=E8=B4=A5=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#279)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/notify/sms/aliyun/AliyunSmsTemplate.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsTemplate.java b/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsTemplate.java index 63da4da7..254622aa 100755 --- a/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsTemplate.java +++ b/jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsTemplate.java @@ -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 { } public String createTtsParam(Map ctx) { - return JSON.toJSONString(ctx); + Map variables = getVariables(); + return JSON.toJSONString(Maps.filterEntries( + renderMap(ctx), + e -> variables.containsKey(e.getKey()))); } @Override -- Gitee From edb692d1a457ee25b20a2cee64faa92ad7b0165b Mon Sep 17 00:00:00 2001 From: zeje Date: Fri, 5 May 2023 12:02:22 +0800 Subject: [PATCH 48/50] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=20(#277)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 蔡泽智 --- .../ResetDeviceConfigurationResult.java | 35 ++++++ .../DefaultDeviceConfigMetadataManager.java | 13 ++ .../service/DeviceConfigMetadataManager.java | 10 ++ .../service/LocalDeviceInstanceService.java | 119 ++++++++++++------ .../device/web/DeviceInstanceController.java | 18 +++ 5 files changed, 157 insertions(+), 38 deletions(-) create mode 100644 jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/ResetDeviceConfigurationResult.java diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/ResetDeviceConfigurationResult.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/ResetDeviceConfigurationResult.java new file mode 100644 index 00000000..e5dad757 --- /dev/null +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/ResetDeviceConfigurationResult.java @@ -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()); + } +} diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java index 896cc39c..55476e80 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DefaultDeviceConfigMetadataManager.java @@ -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> 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) { diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java index 61422fce..264f85cf 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceConfigMetadataManager.java @@ -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> getProductConfigMetadataProperties(String productId); /** * 根据产品ID和网关ID获取配置信息 diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceInstanceService.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceInstanceService.java index 07f83661..119c8058 100755 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceInstanceService.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/LocalDeviceInstanceService.java @@ -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 findByProductId(String productId) { + return createQuery() + .and(DeviceInstanceEntity::getProductId, productId) + .fetch(); + } + + private Set getProductConfigurationProperties(DeviceProductEntity product) { + if (MapUtils.isNotEmpty(product.getConfiguration())) { + return product.getConfiguration() + .keySet(); + } + return new HashSet<>(); + } + + private Mono> 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 { 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 resetConfiguration(Flux payload) { + return payload + .flatMap(deviceId -> resetConfiguration(deviceId)).count(); + } + + /** + * 重置设备配置信息(根据产品批量重置,性能欠佳,慎用) + * + * @param productId 产品ID + * @return 数量 + */ + public Flux 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)); + }); + }) + ); } /** diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java index f13c5163..26ccec6f 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java @@ -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 resetConfigurationBatch(@RequestBody Flux payload) { + return service.resetConfiguration(payload); + } + + @GetMapping(value = "/configuration/_reset/{productId:.+}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + @ResourceAction( + id = "batchResetConf", + name = "批量重置设备配置信息" + ) + @Operation(summary = "重置设备配置信息(根据产品批量重置,性能欠佳,慎用)") + public Flux resetConfigurationBatch(@PathVariable @Parameter(description = "产品ID") String productId) { + return service.resetConfigurationByProductId(productId); + } + //批量激活设备 @GetMapping(value = "/deploy", produces = MediaType.TEXT_EVENT_STREAM_VALUE) @SaveAction -- Gitee From 72362b25088ee2257d8248dab3602534b3dedef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8?= Date: Fri, 5 May 2023 19:16:32 +0800 Subject: [PATCH 49/50] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e8855d16..64b22b01 100644 --- a/README.md +++ b/README.md @@ -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) -- Gitee From a9b906a0d52bd2883674da3cddd844425c6901e9 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 8 May 2023 16:45:22 +0800 Subject: [PATCH 50/50] =?UTF-8?q?fix(=E8=AE=BE=E5=A4=87=E4=BC=9A=E8=AF=9D)?= =?UTF-8?q?:=20=E4=BF=AE=E5=A4=8D=E8=AE=BE=E7=BD=AEDeviceOnlineMessage=20h?= =?UTF-8?q?eader=E6=97=A0=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/DeviceMessageConnector.java | 69 ++++++++++--------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/DeviceMessageConnector.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/DeviceMessageConnector.java index b7406d33..6f83fb92 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/DeviceMessageConnector.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/DeviceMessageConnector.java @@ -110,7 +110,7 @@ public class DeviceMessageConnector implements DecodedClientMessageHandler { Message msg = ((ChildDeviceMessage) message).getChildDeviceMessage(); if (msg instanceof DeviceMessage) { builder.append("/message/children/") - .append(((DeviceMessage) msg).getDeviceId()); + .append(((DeviceMessage) msg).getDeviceId()); } else { builder.append("/message/children"); } @@ -121,7 +121,7 @@ public class DeviceMessageConnector implements DecodedClientMessageHandler { Message msg = ((ChildDeviceMessageReply) message).getChildDeviceMessage(); if (msg instanceof DeviceMessage) { builder.append("/message/children/reply/") - .append(((DeviceMessage) msg).getDeviceId()); + .append(((DeviceMessage) msg).getDeviceId()); } else { builder.append("/message/children/reply"); } @@ -142,48 +142,51 @@ public class DeviceMessageConnector implements DecodedClientMessageHandler { this.registry = registry; this.eventBus = eventBus; this.messageHandler = messageHandler; - sessionManager.listenEvent(event->{ - if(event.isClusterExists()){ + sessionManager.listenEvent(event -> { + if (event.isClusterExists()) { return Mono.empty(); } //从会话管理器里监听会话注册,转发为设备上线消息 - if(event.getType()== DeviceSessionEvent.Type.unregister){ - return this.handleSessionUnregister(event.getSession()); + if (event.getType() == DeviceSessionEvent.Type.unregister) { + return handleSessionMessage(new DeviceOnlineMessage(),event.getSession()); } //从会话管理器里监听会话注销,转发为设备离线消息 - if(event.getType()== DeviceSessionEvent.Type.register){ - return this.handleSessionRegister(event.getSession()); + if (event.getType() == DeviceSessionEvent.Type.register) { + return handleSessionMessage(new DeviceOfflineMessage(),event.getSession()); } return Mono.empty(); }); } + private Mono handleSessionMessage(CommonDeviceMessage message, DeviceSession session) { + return Mono.deferContextual(ctx -> { - protected Mono handleSessionRegister(DeviceSession session) { - DeviceOnlineMessage message = new DeviceOnlineMessage(); - message.addHeader("from", "session-register"); - //添加客户端地址信息 - message.addHeader("address", session.getClientAddress().map(InetSocketAddress::toString).orElse("")); - message.setDeviceId(session.getDeviceId()); - message.setTimestamp(System.currentTimeMillis()); - return this - .onMessage(message) - .onErrorResume(doOnError); - } + //填充触发会话的header信息 + ctx.getOrEmpty(DeviceMessage.class) + .ifPresent(msg -> { + if (msg.getHeaders() != null) { + msg.getHeaders().forEach(message::addHeaderIfAbsent); + } + //上线离线由何种消息触发 + message.addHeader("_createBy", msg.getMessageType().name()); + }); + + message.setDeviceId(session.getDeviceId()); + message.setTimestamp(System.currentTimeMillis()); + + message.addHeader("connectTime", session.connectTime()); + message.addHeader("from", "session"); + //子设备会话时添加上级设备id到header中,下游可以直接通过获取header来获取上级设备id + if (session.isWrapFrom(ChildrenDeviceSession.class)) { + ChildrenDeviceSession child = session.unwrap(ChildrenDeviceSession.class); + message.addHeader("parentId", child.getParentDevice().getDeviceId()); + } + return this + .onMessage(message) + .onErrorResume(doOnError); + + }); - protected Mono handleSessionUnregister(DeviceSession session) { - DeviceOfflineMessage message = new DeviceOfflineMessage(); - message.addHeader("from", "session-unregister"); - message.setDeviceId(session.getDeviceId()); - message.setTimestamp(System.currentTimeMillis()); - //子设备会话时添加上级设备id到header中,下游可以直接通过获取header来获取上级设备id - if (session.isWrapFrom(ChildrenDeviceSession.class)) { - ChildrenDeviceSession child = session.unwrap(ChildrenDeviceSession.class); - message.addHeader("parentId", child.getParentDevice().getDeviceId()); - } - return this - .onMessage(message) - .onErrorResume(doOnError); } public static Flux createDeviceMessageTopic(DeviceRegistry deviceRegistry, Message message) { @@ -206,7 +209,7 @@ public class DeviceMessageConnector implements DecodedClientMessageHandler { List topics = new ArrayList<>(2); topics.add(topic); configs.getValue(PropertyConstants.orgId) - .ifPresent(orgId -> topics.add("/org/" + orgId + topic)); + .ifPresent(orgId -> topics.add("/org/" + orgId + topic)); return topics; }); -- Gitee