新增实时监控功能

左边是设备通道树,右边是分屏预览
This commit is contained in:
朱俊杰
2022-02-10 14:45:33 +08:00
parent d07a5680f3
commit 37a84e6691
24 changed files with 1322 additions and 16 deletions

View File

@@ -0,0 +1,12 @@
package com.genersoft.iot.vmp.utils;
import java.util.Arrays;
public class CollectionUtil {
public static <T> boolean contains(T[] array, final T element) {
return array != null && Arrays.stream(array).anyMatch((x) -> {
return ObjectUtils.nullSafeEquals(x, element);
});
}
}

View File

@@ -0,0 +1,41 @@
package com.genersoft.iot.vmp.utils;
import java.util.Arrays;
public class ObjectUtils {
public static boolean nullSafeEquals(Object o1, Object o2) {
if (o1 == o2) {
return true;
} else if (o1 != null && o2 != null) {
if (o1.equals(o2)) {
return true;
} else {
return o1.getClass().isArray() && o2.getClass().isArray() && arrayEquals(o1, o2);
}
} else {
return false;
}
}
private static boolean arrayEquals(Object o1, Object o2) {
if (o1 instanceof Object[] && o2 instanceof Object[]) {
return Arrays.equals((Object[])((Object[])o1), (Object[])((Object[])o2));
} else if (o1 instanceof boolean[] && o2 instanceof boolean[]) {
return Arrays.equals((boolean[])((boolean[])o1), (boolean[])((boolean[])o2));
} else if (o1 instanceof byte[] && o2 instanceof byte[]) {
return Arrays.equals((byte[])((byte[])o1), (byte[])((byte[])o2));
} else if (o1 instanceof char[] && o2 instanceof char[]) {
return Arrays.equals((char[])((char[])o1), (char[])((char[])o2));
} else if (o1 instanceof double[] && o2 instanceof double[]) {
return Arrays.equals((double[])((double[])o1), (double[])((double[])o2));
} else if (o1 instanceof float[] && o2 instanceof float[]) {
return Arrays.equals((float[])((float[])o1), (float[])((float[])o2));
} else if (o1 instanceof int[] && o2 instanceof int[]) {
return Arrays.equals((int[])((int[])o1), (int[])((int[])o2));
} else if (o1 instanceof long[] && o2 instanceof long[]) {
return Arrays.equals((long[])((long[])o1), (long[])((long[])o2));
} else {
return o1 instanceof short[] && o2 instanceof short[] && Arrays.equals((short[]) ((short[]) o1), (short[]) ((short[]) o2));
}
}
}

View File

@@ -0,0 +1,54 @@
package com.genersoft.iot.vmp.utils.node;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 节点基类
*
*/
@Data
public class BaseNode<T> implements INode<T> {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
protected String id;
/**
* 父节点ID
*/
protected String parentId;
/**
* 子孙节点
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
protected List<T> children = new ArrayList<T>();
/**
* 是否有子孙节点
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Boolean hasChildren;
/**
* 是否有子孙节点
*
* @return Boolean
*/
@Override
public Boolean getHasChildren() {
if (children.size() > 0) {
return true;
} else {
return this.hasChildren;
}
}
}

View File

@@ -0,0 +1,28 @@
package com.genersoft.iot.vmp.utils.node;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 森林节点类
*
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ForestNode extends BaseNode<ForestNode> {
private static final long serialVersionUID = 1L;
/**
* 节点内容
*/
private Object content;
public ForestNode(String id, String parentId, Object content) {
this.id = id;
this.parentId = parentId;
this.content = content;
}
}

View File

@@ -0,0 +1,68 @@
package com.genersoft.iot.vmp.utils.node;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 森林管理类
*
* @author smallchill
*/
public class ForestNodeManager<T extends INode<T>> {
/**
* 森林的所有节点
*/
private final ImmutableMap<String, T> nodeMap;
/**
* 森林的父节点ID
*/
private final Map<String, Object> parentIdMap = Maps.newHashMap();
public ForestNodeManager(List<T> nodes) {
nodeMap = Maps.uniqueIndex(nodes, INode::getId);
}
/**
* 根据节点ID获取一个节点
*
* @param id 节点ID
* @return 对应的节点对象
*/
public INode<T> getTreeNodeAt(String id) {
if (nodeMap.containsKey(id)) {
return nodeMap.get(id);
}
return null;
}
/**
* 增加父节点ID
*
* @param parentId 父节点ID
*/
public void addParentId(String parentId) {
parentIdMap.put(parentId, "");
}
/**
* 获取树的根节点(一个森林对应多颗树)
*
* @return 树的根节点集合
*/
public List<T> getRoot() {
List<T> roots = new ArrayList<>();
nodeMap.forEach((key, node) -> {
if (node.getParentId() == null || parentIdMap.containsKey(node.getId())) {
roots.add(node);
}
});
return roots;
}
}

View File

@@ -0,0 +1,51 @@
package com.genersoft.iot.vmp.utils.node;
import com.genersoft.iot.vmp.utils.CollectionUtil;
import java.util.List;
/**
* 森林节点归并类
*
*/
public class ForestNodeMerger {
/**
* 将节点数组归并为一个森林多棵树填充节点的children域
* 时间复杂度为O(n^2)
*
* @param items 节点域
* @return 多棵树的根节点集合
*/
public static <T extends INode<T>> List<T> merge(List<T> items) {
ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items);
items.forEach(forestNode -> {
if (forestNode.getParentId() != null) {
INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId());
if (node != null) {
node.getChildren().add(forestNode);
} else {
forestNodeManager.addParentId(forestNode.getId());
}
}
});
return forestNodeManager.getRoot();
}
public static <T extends INode<T>> List<T> merge(List<T> items, String[] parentIds) {
ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items);
items.forEach(forestNode -> {
if (forestNode.getParentId() != null) {
INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId());
if (CollectionUtil.contains(parentIds, forestNode.getId())){
forestNodeManager.addParentId(forestNode.getId());
} else {
if (node != null){
node.getChildren().add(forestNode);
}
}
}
});
return forestNodeManager.getRoot();
}
}

View File

@@ -0,0 +1,42 @@
package com.genersoft.iot.vmp.utils.node;
import java.io.Serializable;
import java.util.List;
/**
*
* 节点
*/
public interface INode<T> extends Serializable {
/**
* 主键
*
* @return String
*/
String getId();
/**
* 父主键
*
* @return String
*/
String getParentId();
/**
* 子孙节点
*
* @return List<T>
*/
List<T> getChildren();
/**
* 是否有子孙节点
*
* @return Boolean
*/
default Boolean getHasChildren() {
return false;
}
}

View File

@@ -0,0 +1,21 @@
package com.genersoft.iot.vmp.utils.node;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 树型节点类
*
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TreeNode extends BaseNode<TreeNode> {
private static final long serialVersionUID = 1L;
private String title;
private String key;
private String value;
}