mirror of
https://gitee.com/NexIoT/Universal-IoT-Java.git
synced 2026-10-31 02:52:27 +08:00
chore(release): 版本更新汇总 (2025-08-10 至 2025-09-23)
核心功能优化: - 新增UDP模块并默认开启,TCP基础上增加UDP适配 - 支持网关绑定多产品子设备,优化设备重连机制 - 新增Ezviz(萤石)接入模块,调整imoulife支持自有平台账号 性能与稳定性: - 优化设备影子热数据存储,增加强制刷盘功能 - 产品列表及MQTT查询增加多级缓存策略 - 强化TCP安全机制,新增异常攻击封禁策略 功能完善: - 集成rulego可视化规则引擎基础框架 - Web-IDE新增20+ modbus/hex封装方法 - 优化乐城播放器界面及TCP连接信息展示 问题修复: - 解决系统间强依赖及注入相关问题 - 修复时间格式化、设备创建时间显示问题 - 完善日志处理及应用推送相关异常 其他改进: - 重构TCP粘包处理,删除冗余代码 - 增加Docker部署配置 - 细化权限控制策略
This commit is contained in:
@@ -114,7 +114,12 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.universal.iot</groupId>
|
||||
<artifactId>cn-universal-notice</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2025, IoT-Universal. All Rights Reserved.
|
||||
*
|
||||
* @Description: 本文件由 Aleo 开发并拥有版权,未经授权严禁擅自商用、复制或传播。
|
||||
* @Author: Aleo
|
||||
* @Email: wo8335224@gmail.com
|
||||
* @Wechat: outlookFil
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package cn.universal.admin.network.doc;
|
||||
|
||||
/**
|
||||
* 网络组件API文档
|
||||
*
|
||||
* @version 1.0 @Author Aleo
|
||||
* @since 2025/1/20
|
||||
*/
|
||||
public class NetworkApiDoc {
|
||||
|
||||
/**
|
||||
* 网络组件管理API文档
|
||||
*
|
||||
* <p>基础路径: /admin/network
|
||||
*
|
||||
* <p>1. 查询网络组件列表 GET /admin/network/list 参数: - page: 页码 (可选,默认1) - size: 每页大小 (可选,默认10) - type:
|
||||
* 网络类型 (可选,单个类型,如 TCP_CLIENT) - types: 网络类型列表 (可选,多个类型,如 ["MQTT_CLIENT", "MQTT_SERVER"]) - name:
|
||||
* 网络组件名称 (可选,模糊查询) - productKey: 产品Key (可选) - state: 状态 (可选,true/false) - unionId: 唯一标识 (可选)
|
||||
*
|
||||
* <p>2. 查询网络组件列表(支持多个类型) GET /admin/network/list/multi-type 参数: - page: 页码 (可选,默认1) - size: 每页大小
|
||||
* (可选,默认10) - type: 网络类型 (可选,支持逗号分隔多个类型,如 "MQTT_CLIENT,MQTT_SERVER") - name: 网络组件名称 (可选,模糊查询) -
|
||||
* productKey: 产品Key (可选) - state: 状态 (可选,true/false) - unionId: 唯一标识 (可选)
|
||||
*
|
||||
* <p>3. 根据ID查询网络组件 GET /admin/network/{id} 参数: - id: 网络组件ID (路径参数)
|
||||
*
|
||||
* <p>4. 新增网络组件 POST /admin/network 请求体: { "type": "TCP_SERVER", "unionId": "unique_id",
|
||||
* "productKey": "product_key", "name": "网络组件名称", "description": "详细描述", "state": false,
|
||||
* "configuration": "{\"host\":\"0.0.0.0\",\"port\":6372,\"ssl\":false}", "createUser": "admin" }
|
||||
*
|
||||
* <p>5. 修改网络组件 PUT /admin/network 请求体: { "id": 1, "type": "TCP_SERVER", "unionId": "unique_id",
|
||||
* "productKey": "product_key", "name": "网络组件名称", "description": "详细描述", "state": false,
|
||||
* "configuration": "{\"host\":\"0.0.0.0\",\"port\":6372,\"ssl\":false}" }
|
||||
*
|
||||
* <p>6. 删除网络组件 DELETE /admin/network/{id} 参数: - id: 网络组件ID (路径参数)
|
||||
*
|
||||
* <p>7. 批量删除网络组件 DELETE /admin/network/batch/{ids} 参数: - ids: 网络组件ID数组 (路径参数,逗号分隔)
|
||||
*
|
||||
* <p>8. 启动网络组件 POST /admin/network/start/{id} 参数: - id: 网络组件ID (路径参数)
|
||||
*
|
||||
* <p>9. 停止网络组件 POST /admin/network/stop/{id} 参数: - id: 网络组件ID (路径参数)
|
||||
*
|
||||
* <p>10. 重启网络组件 POST /admin/network/restart/{id} 参数: - id: 网络组件ID (路径参数)
|
||||
*
|
||||
* <p>11. 获取网络类型列表 GET /admin/network/types
|
||||
*
|
||||
* <p>12. 验证网络组件配置 POST /admin/network/validate 请求体: { "type": "TCP_SERVER", "unionId":
|
||||
* "unique_id", "name": "网络组件名称", "configuration":
|
||||
* "{\"host\":\"0.0.0.0\",\"port\":6372,\"ssl\":false}" }
|
||||
*
|
||||
* <p>响应格式: { "code": 200, "msg": "操作成功", "data": { // 具体数据 } }
|
||||
*
|
||||
* <p>网络类型说明: - TCP_CLIENT: TCP客户端 - TCP_SERVER: TCP服务端 - MQTT_CLIENT: MQTT客户端 - MQTT_SERVER:
|
||||
* MQTT服务端
|
||||
*
|
||||
* <p>配置示例:
|
||||
*
|
||||
* <p>TCP_SERVER配置: { "allIdleTime": 0, "allowInsert": false, "alwaysPreDecode": false,
|
||||
* "decoderType": "STRING", "host": "0.0.0.0", "idleInterval": 0, "onlyCache": false,
|
||||
* "parserConfiguration": { "byteOrderLittle": true, "delimited": "]", "delimitedMaxlength": 1024,
|
||||
* "failFast": true }, "parserType": "DELIMITED", "port": 6372, "productKey":
|
||||
* "630477f1cd68445d90b04653", "readerIdleTime": 360, "readTimeout": 0, "sendTimeout": 0, "ssl":
|
||||
* false, "writerIdleTime": 0 }
|
||||
*
|
||||
* <p>MQTT_SERVER配置: { "autoReconnect": true, "cleanSession": true, "clientIdPrefix": "univ_cli_",
|
||||
* "defaultQos": 1, "enabled": true, "host": "tcp://125.210.48.96:1883", "id":
|
||||
* "6863896d75386b5c1e7e908c", "keepAliveInterval": 60, "password": "univiot@2025!", "productKey":
|
||||
* "local", "ssl": false, "subscribeTopics": "$univ_cli/up/property/+/+", "username": "univ_cli",
|
||||
* "connectTimeout": 30 }
|
||||
*/
|
||||
}
|
||||
-10
@@ -29,26 +29,16 @@ import java.util.List;
|
||||
*/
|
||||
public interface INetworkService {
|
||||
|
||||
boolean start(String productKey);
|
||||
|
||||
boolean stop(String productKey);
|
||||
|
||||
Object get(String productKey);
|
||||
|
||||
boolean del(String productKey);
|
||||
|
||||
List<NetworkVO> selectNetworkList(NetworkBO bo);
|
||||
|
||||
NetworkVO getDetail(Long id);
|
||||
|
||||
List<IoTDevice> queryMileSightList(NetworkBO bo);
|
||||
|
||||
R insertDevInstance(IoTDeviceBO devInstancebo);
|
||||
|
||||
R deleteDevInstanceByIds(String[] ids);
|
||||
|
||||
void reloadTcpClient(String applicationId);
|
||||
|
||||
/**
|
||||
* 查询网络组件列表
|
||||
*
|
||||
|
||||
+243
-54
@@ -12,6 +12,7 @@
|
||||
|
||||
package cn.universal.admin.network.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
@@ -25,12 +26,15 @@ import cn.universal.common.domain.R;
|
||||
import cn.universal.common.enums.NetworkType;
|
||||
import cn.universal.common.exception.IoTException;
|
||||
import cn.universal.core.service.IoTDownlFactory;
|
||||
import cn.universal.dm.device.service.protocol.ProtocolClusterService;
|
||||
import cn.universal.dm.device.service.protocol.ProtocolServerManager;
|
||||
import cn.universal.mqtt.protocol.third.ThirdMQTTServerManager;
|
||||
import cn.universal.persistence.entity.IoTDevice;
|
||||
import cn.universal.persistence.entity.IoTProduct;
|
||||
import cn.universal.persistence.entity.IoTUser;
|
||||
import cn.universal.persistence.entity.Network;
|
||||
import cn.universal.persistence.entity.bo.IoTDeviceBO;
|
||||
import cn.universal.persistence.entity.bo.IoTProductBO;
|
||||
import cn.universal.persistence.entity.bo.NetworkBO;
|
||||
import cn.universal.persistence.entity.vo.IoTProductVO;
|
||||
import cn.universal.persistence.entity.vo.NetworkVO;
|
||||
@@ -49,6 +53,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tk.mybatis.mapper.entity.Example;
|
||||
@@ -63,11 +68,8 @@ import tk.mybatis.mapper.entity.Example;
|
||||
@Service
|
||||
public class NetworkServiceImpl implements INetworkService {
|
||||
|
||||
@Autowired
|
||||
private NetworkMapper networkMapper;
|
||||
|
||||
@Resource
|
||||
private NetworkMapper netWorkMapper;
|
||||
private NetworkMapper networkMapper;
|
||||
@Resource
|
||||
private IoTDeviceMapper ioTDeviceMapper;
|
||||
@Resource
|
||||
@@ -75,42 +77,31 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
@Resource
|
||||
private IoTDeviceFenceRelMapper ioTDeviceFenceRelMapper;
|
||||
|
||||
// 直接注入 TCP 和 MQTT 服务
|
||||
@Qualifier("tcpClusterService")
|
||||
@Autowired(required = false)
|
||||
private ProtocolClusterService tcpClusterService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ProtocolServerManager tcpServerManager;
|
||||
|
||||
@Qualifier("udpClusterService")
|
||||
@Autowired(required = false)
|
||||
private ProtocolClusterService udpClusterService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ThirdMQTTServerManager mqttServerManager;
|
||||
|
||||
@Override
|
||||
public boolean start(String productKey) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop(String productKey) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String productKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean del(String productKey) {
|
||||
Example ex = new Example(Network.class);
|
||||
ex.createCriteria().andEqualTo("productKey", productKey);
|
||||
return netWorkMapper.deleteByExample(ex) > 0;
|
||||
return networkMapper.deleteByExample(ex) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NetworkVO> selectNetworkList(NetworkBO bo) {
|
||||
return netWorkMapper.selectNetworkListV1(bo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkVO getDetail(Long id) {
|
||||
return netWorkMapper.selectById(id);
|
||||
return networkMapper.selectNetworkListV1(bo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -182,10 +173,6 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
return R.ok("删除成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadTcpClient(String applicationId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NetworkBO> selectNetworkList(NetworkQuery query) {
|
||||
// 验证类型参数
|
||||
@@ -214,9 +201,32 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
String unionId = bo.getUnionId();
|
||||
if (NetworkType.TCP_CLIENT.getId().equals(type) || NetworkType.TCP_SERVER.getId()
|
||||
.equals(type)) {
|
||||
if (tcpClusterService != null && tcpServerManager != null) {
|
||||
Object serverInstance = tcpServerManager.getServerInstance(productKey);
|
||||
if (serverInstance != null && tcpServerManager.isAlive(serverInstance)) {
|
||||
bo.setStateName("已启动");
|
||||
bo.setRunning(Boolean.TRUE);
|
||||
} else {
|
||||
bo.setStateName("未启动");
|
||||
bo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
} else {
|
||||
bo.setStateName("未启动");
|
||||
bo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
// 查出哪些TCP-Server绑定了产品
|
||||
if (NetworkType.TCP_SERVER.getId().equals(type)) {
|
||||
IoTProductBO ioTProductBO = ioTProductMapper.selectTcpProductsUseNetwork(
|
||||
bo.getProductKey());
|
||||
bo.setBindTcpServerProductCount(ioTProductBO == null ? 0 : 1);
|
||||
bo.setBindTcpServerProducts(ioTProductBO);
|
||||
}
|
||||
|
||||
} else if (NetworkType.MQTT_CLIENT.getId().equals(type) || NetworkType.MQTT_SERVER.getId()
|
||||
.equals(type)) {
|
||||
List<IoTProductBO> ioTProductBOS = ioTProductMapper.selectMqttProductsUseNetwork(unionId);
|
||||
bo.setBindMqttServerProductCount(CollUtil.size(ioTProductBOS));
|
||||
bo.setBindMqttServerProducts(ioTProductBOS);
|
||||
if (mqttServerManager != null && mqttServerManager.isConnected(unionId)) {
|
||||
bo.setStateName("已启动");
|
||||
bo.setRunning(Boolean.TRUE);
|
||||
@@ -224,6 +234,14 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
bo.setStateName("未启动");
|
||||
bo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
} else if (NetworkType.UDP.getId().equals(type)) {
|
||||
if (udpClusterService != null && udpClusterService.isProductServerAlive(productKey)) {
|
||||
bo.setStateName("已启动");
|
||||
bo.setRunning(Boolean.TRUE);
|
||||
} else {
|
||||
bo.setStateName("未启动");
|
||||
bo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
} else {
|
||||
bo.setStateName("未知");
|
||||
bo.setRunning(Boolean.FALSE);
|
||||
@@ -264,6 +282,9 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
case NetworkTypeConstants.MQTT_SERVER:
|
||||
vo.setTypeName(NetworkType.MQTT_SERVER.getDescription());
|
||||
break;
|
||||
case NetworkTypeConstants.UDP:
|
||||
vo.setTypeName(NetworkType.UDP.getDescription());
|
||||
break;
|
||||
default:
|
||||
vo.setTypeName(network.getType());
|
||||
}
|
||||
@@ -275,7 +296,19 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
String unionId = network.getUnionId();
|
||||
if (NetworkType.TCP_CLIENT.getId().equals(type) || NetworkType.TCP_SERVER.getId()
|
||||
.equals(type)) {
|
||||
//TODO 开源版本无
|
||||
if (tcpClusterService != null && tcpServerManager != null) {
|
||||
Object serverInstance = tcpServerManager.getServerInstance(productKey);
|
||||
if (serverInstance != null && tcpServerManager.isAlive(serverInstance)) {
|
||||
vo.setStateName("已启动");
|
||||
vo.setRunning(Boolean.TRUE);
|
||||
} else {
|
||||
vo.setStateName("未启动");
|
||||
vo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
} else {
|
||||
vo.setStateName("未启动");
|
||||
vo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
|
||||
} else if (NetworkType.MQTT_CLIENT.getId().equals(type) || NetworkType.MQTT_SERVER.getId()
|
||||
.equals(type)) {
|
||||
@@ -286,6 +319,14 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
vo.setStateName("未启动");
|
||||
vo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
} else if (NetworkType.UDP.getId().equals(type)) {
|
||||
if (udpClusterService != null && udpClusterService.isProductServerAlive(productKey)) {
|
||||
vo.setStateName("已启动");
|
||||
vo.setRunning(Boolean.TRUE);
|
||||
} else {
|
||||
vo.setStateName("未启动");
|
||||
vo.setRunning(Boolean.FALSE);
|
||||
}
|
||||
} else {
|
||||
vo.setStateName("未知");
|
||||
vo.setRunning(Boolean.FALSE);
|
||||
@@ -347,11 +388,11 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
network.setUnionId(IdUtil.objectId());
|
||||
network.setState(false);
|
||||
|
||||
// 新增TCP_SERVER时,必须指定productKey,并且不能重复绑定
|
||||
// 新增TCP_SERVER/UDP时,必须指定productKey,并且不能重复绑定
|
||||
if (NetworkType.TCP_SERVER.getId().equals(network.getType()) || NetworkType.TCP_CLIENT.getId()
|
||||
.equals(network.getType())) {
|
||||
.equals(network.getType()) || NetworkType.UDP.getId().equals(network.getType())) {
|
||||
if (StrUtil.isBlank(network.getProductKey())) {
|
||||
throw new RuntimeException("TCP服务组件必须选择产品");
|
||||
throw new RuntimeException("TCP/UDP服务组件必须选择产品");
|
||||
}
|
||||
network.setUnionId(network.getProductKey());
|
||||
// 检查是否已被绑定
|
||||
@@ -391,8 +432,8 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
}
|
||||
|
||||
String type = existNetwork.getType();
|
||||
if ((NetworkType.TCP_SERVER.getId().equals(type) || NetworkType.TCP_CLIENT.getId()
|
||||
.equals(type))) {
|
||||
if ((NetworkType.TCP_SERVER.getId().equals(type) || NetworkType.TCP_CLIENT.getId().equals(type)
|
||||
|| NetworkType.UDP.getId().equals(type))) {
|
||||
// 只有当unionId发生变化时,才做"已被产品关联且产品下有设备时禁止修改"的校验
|
||||
String oldProductKey = existNetwork.getProductKey();
|
||||
String networkProductKey = network.getProductKey();
|
||||
@@ -423,9 +464,9 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
throw new RuntimeException("网络组件不存在");
|
||||
}
|
||||
String type = network.getType();
|
||||
// 只对TCP_SERVER和TCP_CLIENT做判断
|
||||
if (NetworkType.TCP_SERVER.getId().equals(type) || NetworkType.TCP_CLIENT.getId()
|
||||
.equals(type)) {
|
||||
// 只对TCP_SERVER、TCP_CLIENT和UDP做判断
|
||||
if (NetworkType.TCP_SERVER.getId().equals(type) || NetworkType.TCP_CLIENT.getId().equals(type)
|
||||
|| NetworkType.UDP.getId().equals(type)) {
|
||||
// 查找是否有关联产品
|
||||
String productKey = ioTProductMapper.findProductKeyByNetworkUnionId(network.getUnionId());
|
||||
if (productKey != null) {
|
||||
@@ -466,6 +507,11 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
if (StrUtil.isBlank(host)) {
|
||||
throw new RuntimeException("MQTT网络组件启动/重启时host不能为空");
|
||||
}
|
||||
} else if (NetworkType.UDP.getId().equals(type)) {
|
||||
Integer port = config.getInt("port");
|
||||
if (port == null) {
|
||||
throw new RuntimeException("UDP网络组件启动/重启时端口不能为空");
|
||||
}
|
||||
}
|
||||
try {
|
||||
// 根据网络类型调用相应的启动逻辑
|
||||
@@ -527,6 +573,11 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
if (StrUtil.isBlank(host)) {
|
||||
throw new RuntimeException("MQTT网络组件启动/重启时host不能为空");
|
||||
}
|
||||
} else if (NetworkType.UDP.getId().equals(type)) {
|
||||
Integer port = config.getInt("port");
|
||||
if (port == null) {
|
||||
throw new RuntimeException("UDP网络组件启动/重启时端口不能为空");
|
||||
}
|
||||
}
|
||||
try {
|
||||
// 根据网络类型调用相应的重启逻辑
|
||||
@@ -548,7 +599,7 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
@Override
|
||||
public List<String> getNetworkTypes() {
|
||||
return Arrays.asList(NetworkType.TCP_CLIENT.getId(), NetworkType.TCP_SERVER.getId(),
|
||||
NetworkType.MQTT_CLIENT.getId(), NetworkType.MQTT_SERVER.getId());
|
||||
NetworkType.MQTT_CLIENT.getId(), NetworkType.MQTT_SERVER.getId(), NetworkType.UDP.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -608,9 +659,9 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
try {
|
||||
JSONObject config = JSONUtil.parseObj(network.getConfiguration());
|
||||
String type = network.getType();
|
||||
// TCP类型检查端口唯一性
|
||||
if (NetworkType.TCP_CLIENT.getId().equals(type) || NetworkType.TCP_SERVER.getId()
|
||||
.equals(type)) {
|
||||
// TCP/UDP类型检查端口唯一性
|
||||
if (NetworkType.TCP_CLIENT.getId().equals(type) || NetworkType.TCP_SERVER.getId().equals(type)
|
||||
|| NetworkType.UDP.getId().equals(type)) {
|
||||
Integer port = config.getInt("port");
|
||||
if (port != null) {
|
||||
List<Network> existingNetworks = networkMapper.selectTcpNetworkByPort(port, excludeId);
|
||||
@@ -663,6 +714,8 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
case NetworkTypeConstants.MQTT_CLIENT:
|
||||
case NetworkTypeConstants.MQTT_SERVER:
|
||||
return startMqttNetwork(network);
|
||||
case NetworkTypeConstants.UDP:
|
||||
return startUdpNetwork(network);
|
||||
default:
|
||||
log.warn("不支持的网络类型: {}", type);
|
||||
return false;
|
||||
@@ -690,6 +743,8 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
case NetworkTypeConstants.MQTT_CLIENT:
|
||||
case NetworkTypeConstants.MQTT_SERVER:
|
||||
return stopMqttNetwork(network);
|
||||
case NetworkTypeConstants.UDP:
|
||||
return stopUdpNetwork(network);
|
||||
default:
|
||||
log.warn("不支持的网络类型: {}", type);
|
||||
return false;
|
||||
@@ -708,7 +763,6 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
*/
|
||||
private boolean restartNetworkByType(Network network) {
|
||||
String type = network.getType();
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case NetworkTypeConstants.TCP_CLIENT:
|
||||
@@ -717,6 +771,8 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
case NetworkTypeConstants.MQTT_CLIENT:
|
||||
case NetworkTypeConstants.MQTT_SERVER:
|
||||
return restartMqttNetwork(network);
|
||||
case NetworkTypeConstants.UDP:
|
||||
return restartUdpNetwork(network);
|
||||
default:
|
||||
log.warn("不支持的网络类型: {}", type);
|
||||
return false;
|
||||
@@ -734,11 +790,28 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
* @return 是否成功
|
||||
*/
|
||||
private boolean startTcpNetwork(Network network) {
|
||||
if (tcpClusterService == null) {
|
||||
log.error("TCP服务管理器未注入,无法启动TCP网络组件: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
String productKey = network.getProductKey();
|
||||
if (StrUtil.isBlank(productKey)) {
|
||||
log.error("TCP网络组件缺少productKey: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
//TODO 开源版本无
|
||||
return true;
|
||||
// 使用新的方法,从数据库加载配置并启动
|
||||
boolean success = tcpClusterService.start(productKey);
|
||||
if (success) {
|
||||
log.info("TCP网络组件启动成功: productKey={}", productKey);
|
||||
} else {
|
||||
log.error("TCP网络组件启动失败: productKey={}", productKey);
|
||||
}
|
||||
return success;
|
||||
} catch (Exception e) {
|
||||
log.error("启动TCP网络组件失败: productKey={}", "", e);
|
||||
log.error("启动TCP网络组件失败: productKey={}", productKey, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -750,17 +823,27 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
* @return 是否成功
|
||||
*/
|
||||
private boolean stopTcpNetwork(Network network) {
|
||||
if (tcpClusterService == null) {
|
||||
log.error("TCP服务管理器未注入,无法停止TCP网络组件: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
String productKey = network.getProductKey();
|
||||
if (StrUtil.isBlank(productKey)) {
|
||||
log.error("TCP网络组件缺少productKey: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
|
||||
return true;
|
||||
try {
|
||||
boolean success = tcpClusterService.stop(productKey);
|
||||
if (success) {
|
||||
log.info("TCP网络组件停止成功: productKey={}", productKey);
|
||||
} else {
|
||||
log.error("TCP网络组件停止失败: productKey={}", productKey);
|
||||
}
|
||||
return success;
|
||||
} catch (Exception e) {
|
||||
log.error("停止TCP网络组件失败: productKey={}", "", e);
|
||||
log.error("停止TCP网络组件失败: productKey={}", productKey, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -772,11 +855,27 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
* @return 是否成功
|
||||
*/
|
||||
private boolean restartTcpNetwork(Network network) {
|
||||
if (tcpClusterService == null) {
|
||||
log.error("TCP服务管理器未注入,无法重启TCP网络组件: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
String productKey = network.getProductKey();
|
||||
if (StrUtil.isBlank(productKey)) {
|
||||
log.error("TCP网络组件缺少productKey: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return true;
|
||||
boolean success = tcpClusterService.restart(productKey);
|
||||
if (success) {
|
||||
log.info("TCP网络组件重启成功: productKey={}", productKey);
|
||||
} else {
|
||||
log.error("TCP网络组件重启失败: productKey={}", productKey);
|
||||
}
|
||||
return success;
|
||||
} catch (Exception e) {
|
||||
log.error("重启TCP网络组件失败: productKey={}", "", e);
|
||||
log.error("重启TCP网络组件失败: productKey={}", productKey, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -881,4 +980,94 @@ public class NetworkServiceImpl implements INetworkService {
|
||||
public IoTDevice getDeviceById(String id) {
|
||||
return ioTDeviceMapper.selectDevInstanceById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动UDP网络组件
|
||||
*
|
||||
* @param network 网络组件
|
||||
* @return 是否成功
|
||||
*/
|
||||
private boolean startUdpNetwork(Network network) {
|
||||
String productKey = network.getProductKey();
|
||||
if (StrUtil.isBlank(productKey)) {
|
||||
log.error("UDP网络组件缺少productKey: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean success;
|
||||
if (udpClusterService != null) {
|
||||
// 使用集群服务启动(会广播到其他节点)
|
||||
success = udpClusterService.start(productKey);
|
||||
log.info("UDP网络组件集群启动: productKey={}, success={}", productKey, success);
|
||||
} else {
|
||||
log.error("UDP集群服务未注入,无法启动UDP网络组件: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
} catch (Exception e) {
|
||||
log.error("启动UDP网络组件失败: productKey={}", productKey, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止UDP网络组件
|
||||
*
|
||||
* @param network 网络组件
|
||||
* @return 是否成功
|
||||
*/
|
||||
private boolean stopUdpNetwork(Network network) {
|
||||
String productKey = network.getProductKey();
|
||||
if (StrUtil.isBlank(productKey)) {
|
||||
log.error("UDP网络组件缺少productKey: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean success;
|
||||
if (udpClusterService != null) {
|
||||
// 使用集群服务停止(会广播到其他节点)
|
||||
success = udpClusterService.stop(productKey);
|
||||
log.info("UDP网络组件集群停止: productKey={}, success={}", productKey, success);
|
||||
} else {
|
||||
log.error("UDP集群服务未注入,无法停止UDP网络组件: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
} catch (Exception e) {
|
||||
log.error("停止UDP网络组件失败: productKey={}", productKey, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重启UDP网络组件
|
||||
*
|
||||
* @param network 网络组件
|
||||
* @return 是否成功
|
||||
*/
|
||||
private boolean restartUdpNetwork(Network network) {
|
||||
String productKey = network.getProductKey();
|
||||
if (StrUtil.isBlank(productKey)) {
|
||||
log.error("UDP网络组件缺少productKey: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean success;
|
||||
if (udpClusterService != null) {
|
||||
// 使用集群服务重启(会广播到其他节点)
|
||||
success = udpClusterService.restart(productKey);
|
||||
log.info("UDP网络组件集群重启: productKey={}, success={}", productKey, success);
|
||||
} else {
|
||||
log.error("UDP集群服务未注入,无法重启UDP网络组件: {}", network.getName());
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
} catch (Exception e) {
|
||||
log.error("重启UDP网络组件失败: productKey={}", productKey, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class NetworkTypeUtil {
|
||||
|
||||
/** 支持的网络类型列表 */
|
||||
public static final List<String> SUPPORTED_TYPES =
|
||||
Arrays.asList("TCP_CLIENT", "TCP_SERVER", "MQTT_CLIENT", "MQTT_SERVER");
|
||||
Arrays.asList("TCP_CLIENT", "TCP_SERVER", "MQTT_CLIENT", "MQTT_SERVER", "UDP");
|
||||
|
||||
/**
|
||||
* 解析网络类型字符串,支持逗号分隔的多个类型
|
||||
|
||||
+3
-4
@@ -329,7 +329,7 @@ public class NetworkController extends BaseController {
|
||||
}
|
||||
|
||||
/** 查询绑定指定星纵网关的设备 */
|
||||
@GetMapping("/milesight/list")
|
||||
@GetMapping("/xz/gateway/list")
|
||||
public TableDataInfo queryMileSightList(NetworkBO bo) {
|
||||
startPage();
|
||||
// 设置用户权限过滤
|
||||
@@ -339,7 +339,7 @@ public class NetworkController extends BaseController {
|
||||
}
|
||||
|
||||
/** 新增设备 */
|
||||
@PostMapping("/milesight/add")
|
||||
@PostMapping("/xz/gateway/add")
|
||||
@Log(title = "新增设备", businessType = BusinessType.INSERT)
|
||||
public R add(@RequestBody IoTDeviceBO devInstancebo) {
|
||||
// 设置创建用户
|
||||
@@ -356,7 +356,7 @@ public class NetworkController extends BaseController {
|
||||
}
|
||||
|
||||
/** 删除设备 */
|
||||
@DeleteMapping("/milesight/{ids}")
|
||||
@DeleteMapping("/xz/gateway/{ids}")
|
||||
@Log(title = "删除设备", businessType = BusinessType.DELETE)
|
||||
public R remove(@PathVariable String[] ids) {
|
||||
// 校验用户权限
|
||||
@@ -385,7 +385,6 @@ public class NetworkController extends BaseController {
|
||||
public R reloadTcpClient(@PathVariable("applicationId") String applicationId) {
|
||||
// 校验用户权限 - 需要根据applicationId获取相关的信息进行权限校验
|
||||
// 这里可能需要额外的业务逻辑来实现权限校验
|
||||
iNetworkService.reloadTcpClient(applicationId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -27,6 +27,7 @@ import cn.universal.persistence.entity.vo.IoTDeviceModelVO;
|
||||
import cn.universal.persistence.entity.vo.IoTDeviceVO;
|
||||
import com.github.pagehelper.Page;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 设备Service接口
|
||||
@@ -147,9 +148,15 @@ public interface IIoTDeviceService {
|
||||
|
||||
List<GatewayDeviceVo> selectGwIotDevices(IoTGwDeviceBO bo);
|
||||
|
||||
IoTDevice selectDeviceByDeviceId(String deviceId);
|
||||
IoTDevice selectIoTDevice(String productKey, String deviceId);
|
||||
|
||||
List<IoTDevice> selectDevInstanceListWithTags(IoTDeviceBO ioTDeviceBO, IoTUser iotUser);
|
||||
|
||||
List<IoTProduct> selectProductListInBatchFunction(Long applicationId, IoTUser iotUser);
|
||||
|
||||
/** 新:按第三方平台过滤设备列表(不影响旧接口) */
|
||||
List<IoTDevice> selectDevInstanceListByPlatform(
|
||||
IoTDevice ioTDevice, IoTUser iotUser, String thirdPlatform);
|
||||
|
||||
|
||||
}
|
||||
|
||||
+3
-1
@@ -178,7 +178,9 @@ public interface IIoTProductService {
|
||||
|
||||
Map<String, Integer> countDevNumberByProductKey(String unionId);
|
||||
|
||||
AjaxResult<IoTProduct> selectDevProductByKey(String key);
|
||||
AjaxResult<IoTProduct> selectIoTProductByKey(String key);
|
||||
|
||||
AjaxResult<List<IoTProduct>> selectGatewaySubProductsByKey(String gwProductKey);
|
||||
|
||||
int updateDevProductOtherConfig(String otherConfig);
|
||||
|
||||
|
||||
+28
-11
@@ -34,6 +34,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -84,7 +85,7 @@ public class IoTDeviceGroupServiceImpl extends BaseServiceImpl implements IIoTDe
|
||||
// 生成设备分组树
|
||||
List<IoTDeviceGroupVO> roots = collect.get(0L);
|
||||
ioTDeviceGroupVO.setChildren(roots);
|
||||
buildGroupTree(roots, collect);
|
||||
groupTree(roots, collect);
|
||||
return groupVos;
|
||||
}
|
||||
|
||||
@@ -192,12 +193,23 @@ public class IoTDeviceGroupServiceImpl extends BaseServiceImpl implements IIoTDe
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定设备到分组
|
||||
* 绑定设备到分组 iot_dev_action
|
||||
*
|
||||
* @param devGroup
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = {
|
||||
"iot_dev_instance_bo",
|
||||
"iot_dev_metadata_bo",
|
||||
"iot_dev_shadow_bo",
|
||||
"iot_dev_action",
|
||||
"selectDevCount",
|
||||
"iot_dev_product_list",
|
||||
"iot_product_device"
|
||||
},
|
||||
allEntries = true)
|
||||
public AjaxResult<Void> bindDevToGroup(IoTDeviceGroupBO devGroup) {
|
||||
// 判断分组是否存在
|
||||
Long groupId = devGroup.getId();
|
||||
@@ -292,6 +304,17 @@ public class IoTDeviceGroupServiceImpl extends BaseServiceImpl implements IIoTDe
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
@CacheEvict(
|
||||
cacheNames = {
|
||||
"iot_dev_instance_bo",
|
||||
"iot_dev_metadata_bo",
|
||||
"iot_dev_shadow_bo",
|
||||
"iot_dev_action",
|
||||
"selectDevCount",
|
||||
"iot_dev_product_list",
|
||||
"iot_product_device"
|
||||
},
|
||||
allEntries = true)
|
||||
public AjaxResult<Void> unBindDevByGroupId(String groupId, String[] devId) {
|
||||
for (int i = 0; i < devId.length; i++) {
|
||||
ioTDeviceTagsMapper.delete(IoTDeviceTags.builder().iotId(devId[i]).value(groupId).build());
|
||||
@@ -299,14 +322,8 @@ public class IoTDeviceGroupServiceImpl extends BaseServiceImpl implements IIoTDe
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成设备分组树
|
||||
*
|
||||
* @param ioTDeviceGroupVO
|
||||
* @param groups
|
||||
* @return
|
||||
*/
|
||||
private void buildGroupTree(
|
||||
/** 生成设备分组列表 */
|
||||
private void groupTree(
|
||||
List<IoTDeviceGroupVO> ioTDeviceGroupVO, Map<Long, List<IoTDeviceGroupVO>> groups) {
|
||||
if (ioTDeviceGroupVO == null) {
|
||||
return;
|
||||
@@ -315,7 +332,7 @@ public class IoTDeviceGroupServiceImpl extends BaseServiceImpl implements IIoTDe
|
||||
if (ioTDeviceGroupVO.get(i).getHasChild() == 1) {
|
||||
List<IoTDeviceGroupVO> devGroups = groups.get(ioTDeviceGroupVO.get(i).getId());
|
||||
ioTDeviceGroupVO.get(i).setChildren(devGroups);
|
||||
buildGroupTree(devGroups, groups);
|
||||
groupTree(devGroups, groups);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
+25
-9
@@ -45,7 +45,6 @@ import cn.universal.persistence.mapper.IoTDeviceProtocolMapper;
|
||||
import cn.universal.persistence.mapper.IoTDeviceShadowMapper;
|
||||
import cn.universal.persistence.mapper.IoTDeviceTagsMapper;
|
||||
import cn.universal.persistence.mapper.IoTProductMapper;
|
||||
import cn.universal.persistence.query.IoTDeviceQuery;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -149,6 +148,13 @@ public class IoTDeviceServiceImpl extends BaseServiceImpl implements IIoTDeviceS
|
||||
ioTDevice, iotUser.isAdmin() ? null : iotUser.getUnionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IoTDevice> selectDevInstanceListByPlatform(
|
||||
IoTDevice ioTDevice, IoTUser iotUser, String thirdPlatform) {
|
||||
return ioTDeviceMapper.selectDevInstanceListByPlatform(
|
||||
ioTDevice, thirdPlatform, iotUser.isAdmin() ? null : iotUser.getUnionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备列表
|
||||
*
|
||||
@@ -229,8 +235,8 @@ public class IoTDeviceServiceImpl extends BaseServiceImpl implements IIoTDeviceS
|
||||
}
|
||||
|
||||
@Override
|
||||
public IoTDevice selectDeviceByDeviceId(String deviceId) {
|
||||
return ioTDeviceMapper.getOneByDeviceId(IoTDeviceQuery.builder().deviceId(deviceId).build());
|
||||
public IoTDevice selectIoTDevice(String productKey, String deviceId) {
|
||||
return ioTDeviceMapper.selectIoTDevice(productKey, deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -270,11 +276,12 @@ public class IoTDeviceServiceImpl extends BaseServiceImpl implements IIoTDeviceS
|
||||
if (ioTDeviceBO.getOtherParams().containsKey("deviceKey")) {
|
||||
ioTDeviceBO.setSecretKey(ioTDeviceBO.getOtherParams().get("deviceKey").toString());
|
||||
}
|
||||
|
||||
if (cn.universal.common.utils.StringUtils.isEmpty(ioTDeviceBO.getLatitude())) {
|
||||
ioTDeviceBO.setLatitude("30.4484801");
|
||||
ioTDeviceBO.setLatitude("44.61081");
|
||||
}
|
||||
if (cn.universal.common.utils.StringUtils.isEmpty(ioTDeviceBO.getLongitude())) {
|
||||
ioTDeviceBO.setLongitude("120.2922654");
|
||||
ioTDeviceBO.setLongitude("80.990372");
|
||||
}
|
||||
if (StrUtil.isNotBlank(deviceId)) {
|
||||
ioTDeviceBO.setGwProductKey(deviceId);
|
||||
@@ -333,6 +340,17 @@ public class IoTDeviceServiceImpl extends BaseServiceImpl implements IIoTDeviceS
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = {
|
||||
"iot_dev_instance_bo",
|
||||
"iot_dev_metadata_bo",
|
||||
"iot_dev_shadow_bo",
|
||||
"iot_dev_action",
|
||||
"selectDevCount",
|
||||
"iot_dev_product_list",
|
||||
"iot_product_device"
|
||||
},
|
||||
allEntries = true)
|
||||
public int bindApp(String ids, String appUniqueId) {
|
||||
String[] a = ids.split(",");
|
||||
return ioTDeviceMapper.bindApp(a, appUniqueId);
|
||||
@@ -362,7 +380,7 @@ public class IoTDeviceServiceImpl extends BaseServiceImpl implements IIoTDeviceS
|
||||
downRequest.set("detail", devInstancebo.getDetail());
|
||||
// 网关产品ProductKey
|
||||
downRequest.set("gwProductKey", devInstancebo.getGwProductKey());
|
||||
downRequest.set("gwDeviceId", devInstancebo.getExtDeviceId());
|
||||
downRequest.set("gwDeviceId", devInstancebo.getGwDeviceId());
|
||||
downRequest.set("extDeviceId", devInstancebo.getExtDeviceId());
|
||||
JSONObject ob = new JSONObject();
|
||||
// 设备实例名称
|
||||
@@ -506,9 +524,7 @@ public class IoTDeviceServiceImpl extends BaseServiceImpl implements IIoTDeviceS
|
||||
public R iotFunctionsDown(String productKey, String downRequest) {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(downRequest);
|
||||
String deviceId = jsonObject.getStr("deviceId");
|
||||
IoTDevice ioTDeviceBo =
|
||||
ioTDeviceMapper.getOneByDeviceId(
|
||||
IoTDeviceQuery.builder().deviceId(deviceId).productKey(productKey).build());
|
||||
IoTDevice ioTDeviceBo = ioTDeviceMapper.selectIoTDevice(productKey, deviceId);
|
||||
if (ioTDeviceBo == null) {
|
||||
return R.error("设备不存在");
|
||||
}
|
||||
|
||||
+148
-35
@@ -25,10 +25,12 @@ import cn.hutool.http.HttpStatus;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.universal.dm.device.service.protocol.ProtocolClusterService;
|
||||
import cn.universal.admin.common.service.BaseServiceImpl;
|
||||
import cn.universal.admin.common.utils.SecurityUtils;
|
||||
import cn.universal.admin.platform.service.IIoTProductService;
|
||||
import cn.universal.admin.system.service.IoTDeviceProtocolService;
|
||||
import cn.universal.cache.annotation.MultiLevelCacheable;
|
||||
import cn.universal.common.constant.IoTConstant;
|
||||
import cn.universal.common.constant.IoTConstant.DeviceNode;
|
||||
import cn.universal.common.constant.IoTConstant.ProductFlushType;
|
||||
@@ -192,31 +194,54 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
}
|
||||
|
||||
@Override
|
||||
// @Cacheable(cacheNames = "iot_dev_product_list", unless = "#result == null", keyGenerator =
|
||||
// "redisKeyGenerate")
|
||||
// 分页查询不使用缓存,因为分页参数会导致缓存键不同,效率低下
|
||||
public List<IoTProductVO> selectDevProductV4List(IoTProductQuery ioTProductQuery) {
|
||||
Page<IoTProductVO> page =
|
||||
PageHelper.startPage(ioTProductQuery.getPageNum(), ioTProductQuery.getPageSize());
|
||||
// 设置分页参数
|
||||
PageHelper.startPage(ioTProductQuery.getPageNum(), ioTProductQuery.getPageSize());
|
||||
|
||||
// 优化:一次SQL查询获取产品列表和设备数量,避免N+1查询
|
||||
List<IoTProductVO> devProductVOS = ioTProductMapper.selectDevProductV3List(ioTProductQuery);
|
||||
List<IoTProductVO> results =
|
||||
ioTProductMapper.countDevNumberByProductKey(ioTProductQuery.getCreatorId());
|
||||
if (CollUtil.isNotEmpty(results)) {
|
||||
final Map<String, Integer> collect =
|
||||
results.stream()
|
||||
.collect(Collectors.toMap(IoTProductVO::getProductKey, IoTProductVO::getDevNum));
|
||||
|
||||
// 处理图片URL
|
||||
if (CollUtil.isNotEmpty(devProductVOS)) {
|
||||
for (IoTProductVO devProduct : devProductVOS) {
|
||||
devProduct.setDevNum(collect.getOrDefault(devProduct.getProductKey(), 0));
|
||||
if (JSONUtil.isTypeJSON(devProduct.getPhotoUrl())) {
|
||||
JSONObject photo = JSONUtil.parseObj(devProduct.getPhotoUrl());
|
||||
devProduct.setImage(photo.getStr("img", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 按设备数量倒序排序
|
||||
// if (CollUtil.isNotEmpty(devProductVOS)) {
|
||||
// devProductVOS.sort(Comparator.comparingInt(IoTProductVO::getDevNum).reversed());
|
||||
// }
|
||||
return page;
|
||||
|
||||
return devProductVOS;
|
||||
}
|
||||
|
||||
/** 获取不分页的产品列表(用于缓存) 缓存基础产品数据,不包含分页信息 */
|
||||
@MultiLevelCacheable(
|
||||
cacheNames = "selectDevProductV4ListNoPage",
|
||||
keyGenerator = "redisKeyGenerate",
|
||||
unless = "#result == null",
|
||||
l1Expire = 30)
|
||||
public List<IoTProductVO> selectDevProductV4ListNoPage(IoTProductQuery ioTProductQuery) {
|
||||
// 创建不分页的查询条件
|
||||
IoTProductQuery noPageQuery = new IoTProductQuery();
|
||||
BeanUtil.copyProperties(ioTProductQuery, noPageQuery);
|
||||
noPageQuery.setPageNum(1);
|
||||
noPageQuery.setPageSize(Integer.MAX_VALUE); // 获取所有数据
|
||||
|
||||
// 优化:一次SQL查询获取产品列表和设备数量,避免N+1查询
|
||||
List<IoTProductVO> devProductVOS = ioTProductMapper.selectDevProductV3List(noPageQuery);
|
||||
|
||||
// 处理图片URL
|
||||
if (CollUtil.isNotEmpty(devProductVOS)) {
|
||||
for (IoTProductVO devProduct : devProductVOS) {
|
||||
if (JSONUtil.isTypeJSON(devProduct.getPhotoUrl())) {
|
||||
JSONObject photo = JSONUtil.parseObj(devProduct.getPhotoUrl());
|
||||
devProduct.setImage(photo.getStr("img", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return devProductVOS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -237,7 +262,9 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
cacheNames = {
|
||||
"iot_all_dev_product_list",
|
||||
"iot_dev_product_list",
|
||||
"selectAllEnableNetworkProductKey"
|
||||
"selectAllEnableNetworkProductKey",
|
||||
"selectDevProductV4ListNoPage",
|
||||
"countDevNumberByProductKey"
|
||||
},
|
||||
allEntries = true)
|
||||
public int insertDevProduct(IoTProduct ioTProduct) {
|
||||
@@ -257,6 +284,9 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
if (StrUtil.isBlank(ioTProduct.getProductSecret())) {
|
||||
ioTProduct.setProductSecret(IdUtil.fastSimpleUUID());
|
||||
}
|
||||
if (StrUtil.isBlank(ioTProduct.getConfiguration())) {
|
||||
ioTProduct.setConfiguration(buildProductCfg(ioTProduct));
|
||||
}
|
||||
ioTProduct.setProductKey(productKey);
|
||||
ioTProduct.setMetadata(defaultMetadata);
|
||||
ioTProduct.setThirdConfiguration(thirdConfig);
|
||||
@@ -268,9 +298,30 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
return i;
|
||||
}
|
||||
|
||||
/** 默认创建mqtt设置自动注册 */
|
||||
private String buildProductCfg(IoTProduct ioTProduct) {
|
||||
JSONObject cfg = new JSONObject();
|
||||
boolean isMqtt = false;
|
||||
String thirdPlatform = ioTProduct == null ? null : ioTProduct.getThirdPlatform();
|
||||
if (thirdPlatform == null) {
|
||||
return JSONUtil.toJsonStr(cfg);
|
||||
}
|
||||
if (ProtocolModule.tcp.name().equalsIgnoreCase(thirdPlatform)
|
||||
|| ProtocolModule.mqtt.name().equalsIgnoreCase(thirdPlatform)
|
||||
|| ProtocolModule.udp.name().equalsIgnoreCase(thirdPlatform)) {
|
||||
cfg.set(IoTConstant.ALLOW_INSERT, true);
|
||||
}
|
||||
return JSONUtil.toJsonStr(cfg);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = {"iot_all_dev_product_list", "iot_dev_product_list"},
|
||||
cacheNames = {
|
||||
"iot_all_dev_product_list",
|
||||
"iot_dev_product_list",
|
||||
"selectDevProductV4ListNoPage",
|
||||
"countDevNumberByProductKey"
|
||||
},
|
||||
allEntries = true)
|
||||
public int insertList(List<IoTProduct> ioTProductList) {
|
||||
int i = ioTProductMapper.insertList(ioTProductList);
|
||||
@@ -280,7 +331,13 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
/** 产品协议导入 */
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = {"iot_all_dev_product_list", "iot_dev_product_list", "supportMQTTNetwork"},
|
||||
cacheNames = {
|
||||
"iot_all_dev_product_list",
|
||||
"iot_dev_product_list",
|
||||
"supportMQTTNetwork",
|
||||
"selectDevProductV4ListNoPage",
|
||||
"countDevNumberByProductKey"
|
||||
},
|
||||
allEntries = true)
|
||||
public String importProduct(List<IoTProductImportBO> productImportBos, String unionId) {
|
||||
Long timeMillis = System.currentTimeMillis();
|
||||
@@ -357,7 +414,9 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
devProduct -> {
|
||||
R r =
|
||||
IoTDownlFactory.safeInvokeDown(
|
||||
ProtocolModule.ctaiot.name(), "downPro", devProduct.getThirdDownRequest());
|
||||
ProtocolModule.ctaiot.name(),
|
||||
IoTConstant.DOWN_TO_THIRD_PLATFORM,
|
||||
devProduct.getThirdDownRequest());
|
||||
if (!R.SUCCESS.equals(r.getCode())) {
|
||||
failedList.add(devProduct);
|
||||
} else {
|
||||
@@ -395,7 +454,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
ioTProductAction.create(null, unionId);
|
||||
String result =
|
||||
String.format(
|
||||
"导入普通产品总数:%s 个,成功:%s个;导入电信产品总数:%s 个,成功:%s 个;导入协议总数:%s 个,成功:%s 个。",
|
||||
"导入普通产品总数:%s 个,成功:%s个;导入电信ctwing产品总数:%s 个,成功:%s 个;导入协议总数:%s 个,成功:%s 个。",
|
||||
customProductList.size() + duplicateNum.get(),
|
||||
customSuccess,
|
||||
ctwingProductList.size(),
|
||||
@@ -413,7 +472,13 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
*/
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = {"iot_all_dev_product_list", "iot_dev_product_list", "supportMQTTNetwork"},
|
||||
cacheNames = {
|
||||
"iot_all_dev_product_list",
|
||||
"iot_dev_product_list",
|
||||
"supportMQTTNetwork",
|
||||
"selectDevProductV4ListNoPage",
|
||||
"countDevNumberByProductKey"
|
||||
},
|
||||
allEntries = true)
|
||||
public int updateDevProduct(IoTProduct ioTProduct) {
|
||||
IoTUser iotUser = queryIotUser(SecurityUtils.getUnionId());
|
||||
@@ -423,7 +488,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
String appUnionId = iotUser.getUnionId();
|
||||
IoTProduct pro = ioTProductMapper.selectByPrimaryKey(ioTProduct.getId());
|
||||
if (!appUnionId.equals(pro.getCreatorId()) && !iotUser.isAdmin()) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("没有产品权限");
|
||||
}
|
||||
if (Objects.nonNull(ioTProduct.getClassifiedId())) {
|
||||
IoTProductSort ioTProductSort =
|
||||
@@ -432,7 +497,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
}
|
||||
|
||||
int count = ioTProductMapper.updateDevProduct(ioTProduct);
|
||||
log.info("修改产品记录数={},修改人={}", count, appUnionId);
|
||||
log.info("updateDevProduct,操作成功={},userId={}", count, appUnionId);
|
||||
ioTProductAction.update(ioTProduct);
|
||||
return count;
|
||||
}
|
||||
@@ -445,7 +510,13 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
*/
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = {"iot_all_dev_product_list", "iot_dev_product_list", "supportMQTTNetwork"},
|
||||
cacheNames = {
|
||||
"iot_all_dev_product_list",
|
||||
"iot_dev_product_list",
|
||||
"supportMQTTNetwork",
|
||||
"selectDevProductV4ListNoPage",
|
||||
"countDevNumberByProductKey"
|
||||
},
|
||||
allEntries = true)
|
||||
public int deleteDevProductByIds(String[] ids) {
|
||||
String appUnionId = queryIotUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
@@ -453,7 +524,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
for (String id : ids) {
|
||||
IoTProduct ioTProduct = ioTProductMapper.selectDevProductById(id);
|
||||
if (!appUnionId.equals(ioTProduct.getCreatorId())) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("无产品权限");
|
||||
}
|
||||
count = +deleteDevProductById(id);
|
||||
}
|
||||
@@ -468,7 +539,13 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
*/
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = {"iot_all_dev_product_list", "iot_dev_product_list", "supportMQTTNetwork"},
|
||||
cacheNames = {
|
||||
"iot_all_dev_product_list",
|
||||
"iot_dev_product_list",
|
||||
"supportMQTTNetwork",
|
||||
"selectDevProductV4ListNoPage",
|
||||
"countDevNumberByProductKey"
|
||||
},
|
||||
allEntries = true)
|
||||
public int deleteDevProductById(String id) {
|
||||
String appUnionId = queryIotUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
@@ -477,7 +554,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
throw new IoTException("产品不存在");
|
||||
}
|
||||
if (!appUnionId.equals(ioTProduct.getCreatorId())) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("无产品权限");
|
||||
}
|
||||
IoTDevice ioTDevice = IoTDevice.builder().productKey(ioTProduct.getProductKey()).build();
|
||||
int count = ioTDeviceMapper.selectCount(ioTDevice);
|
||||
@@ -507,7 +584,8 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
"iot_dev_action",
|
||||
"selectDevCount",
|
||||
"supportMQTTNetwork",
|
||||
"iot_dev_product_list"
|
||||
"iot_dev_product_list",
|
||||
"getProductConfiguration"
|
||||
},
|
||||
allEntries = true)
|
||||
public int updateDevProductConfig(IoTProductVO devProduct) {
|
||||
@@ -518,7 +596,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
throw new IoTException("产品不存在");
|
||||
}
|
||||
if (!appUnionId.equals(product.getCreatorId())) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("无产品权限");
|
||||
}
|
||||
// 获取新的产品配置信息
|
||||
JSONObject newConfig = JSONUtil.parseObj(devProduct.getConfiguration());
|
||||
@@ -802,7 +880,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
String appUnionId = queryIotUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
IoTProduct product = ioTProductMapper.getProductByProductKey(ioTProductBO.getProductKey());
|
||||
if (!appUnionId.equals(product.getCreatorId())) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("无产品权限");
|
||||
}
|
||||
ioTProductBO.setPath(getPath(ioTProductBO));
|
||||
int delCount = ioTProductMapper.deleteMetadata(ioTProductBO);
|
||||
@@ -840,7 +918,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
String appUnionId = queryIotUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
IoTProduct product = ioTProductMapper.getProductByProductKey(ioTProductBO.getProductKey());
|
||||
if (!appUnionId.equals(product.getCreatorId())) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("无产品权限");
|
||||
}
|
||||
ioTProductBO.beanToJson();
|
||||
// if(getMetadata(ioTProductBO)!=null){
|
||||
@@ -884,19 +962,41 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
}
|
||||
|
||||
@Override
|
||||
@MultiLevelCacheable(
|
||||
cacheNames = "countDevNumberByProductKey",
|
||||
keyGenerator = "redisKeyGenerate",
|
||||
unless = "#result == null",
|
||||
l1Expire = 30)
|
||||
public Map<String, Integer> countDevNumberByProductKey(String unionId) {
|
||||
List<IoTProductVO> results = ioTProductMapper.countDevNumberByProductKey(unionId);
|
||||
return results.stream()
|
||||
.collect(Collectors.toMap(IoTProductVO::getProductKey, IoTProductVO::getDevNum));
|
||||
}
|
||||
|
||||
/** 设备数量变化时清除相关缓存 当设备新增、删除、修改时调用此方法 */
|
||||
@CacheEvict(
|
||||
cacheNames = {"countDevNumberByProductKey", "selectDevProductV4ListNoPage"},
|
||||
allEntries = true)
|
||||
public void evictDeviceCountCache() {
|
||||
// 此方法用于手动清除设备数量相关缓存
|
||||
// 当设备数据发生变化时调用
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult<IoTProduct> selectDevProductByKey(String key) {
|
||||
public AjaxResult<IoTProduct> selectIoTProductByKey(String key) {
|
||||
IoTProduct ioTProduct = new IoTProduct();
|
||||
ioTProduct.setProductKey(key);
|
||||
return AjaxResult.success(ioTProductMapper.selectOne(ioTProduct));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult<List<IoTProduct>> selectGatewaySubProductsByKey(String gwProductKey) {
|
||||
IoTProduct ioTProduct = new IoTProduct();
|
||||
ioTProduct.setGwProductKey(gwProductKey);
|
||||
ioTProduct.setState((byte) 0);
|
||||
return AjaxResult.success(ioTProductMapper.select(ioTProduct));
|
||||
}
|
||||
|
||||
/** 修改产品其他配置信息 */
|
||||
@Override
|
||||
@CacheEvict(
|
||||
@@ -917,7 +1017,7 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
IoTProduct product = ioTProductMapper.selectDevProductById(newConfig.getStr("productId"));
|
||||
IoTUser iotUser = queryIotUser(SecurityUtils.getUnionId());
|
||||
if (!product.getCreatorId().equals(iotUser.getUnionId())) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("无产品权限");
|
||||
}
|
||||
// 获取第三方配置
|
||||
String thirdConfiguration = product.getThirdConfiguration();
|
||||
@@ -1042,7 +1142,20 @@ public class IoTProductServiceImpl extends BaseServiceImpl implements IIoTProduc
|
||||
|
||||
@Override
|
||||
public void flushNettyServer(String config, String productKey, TcpFlushType type) {
|
||||
|
||||
JSONObject object = new JSONObject();
|
||||
object.set("type", ProductFlushType.server.name());
|
||||
object.set("productKey", productKey);
|
||||
object.set("customType", type.name());
|
||||
eventPublisher.publishEvent(EventTopics.PRODUCT_CONFIG_UPDATED, object);
|
||||
// 使用ProtocolClusterService进行集群操作
|
||||
ProtocolClusterService tcpClusterService = SpringUtil.getBean(ProtocolClusterService.class);
|
||||
if (tcpClusterService != null) {
|
||||
switch (type) {
|
||||
case start -> tcpClusterService.start(productKey);
|
||||
case reload -> tcpClusterService.restart(productKey);
|
||||
case close -> tcpClusterService.stop(productKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+16
-13
@@ -90,6 +90,18 @@ public class IoTDeviceController extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/** 新:按第三方平台过滤的设备列表(用于萤石/乐橙) */
|
||||
@GetMapping("/listByPlatform")
|
||||
public TableDataInfo listByPlatform(
|
||||
IoTDevice ioTDevice,
|
||||
@RequestParam(value = "thirdPlatform", required = false) String thirdPlatform) {
|
||||
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
startPage();
|
||||
List<IoTDevice> list =
|
||||
iIotDeviceService.selectDevInstanceListByPlatform(ioTDevice, iotUser, thirdPlatform);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/** 查询分组未绑定设备列表 */
|
||||
@GetMapping("/list/{groupId}")
|
||||
public TableDataInfo list(@PathVariable("groupId") String groupId, IoTDevice ioTDevice) {
|
||||
@@ -152,27 +164,18 @@ public class IoTDeviceController extends BaseController {
|
||||
|
||||
/** 获取设备详细信息 */
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
|
||||
public AjaxResult getIotDeviceInfo(@PathVariable("id") String id) {
|
||||
IoTDevice ioTDevice = iIotDeviceService.selectDevInstanceById(id);
|
||||
// if (ObjectUtil.isEmpty(ioTDevice)) {
|
||||
// throw new IoTException("设备不存在");
|
||||
// }
|
||||
// IoTUser iotUser = checkParent(SecurityUtils.getUnionId());
|
||||
// if (!iotUser.isAdmin() && !ioTDevice.getCreatorId()
|
||||
// .equals(iotUser.getUnionId())) {
|
||||
// throw new IoTException("你无权操作");
|
||||
// }
|
||||
// 是否有编解码插件
|
||||
int count = ioTDeviceProtocolService.countProtocol(ioTDevice.getProductKey());
|
||||
IoTDeviceBO ioTDeviceBO = new IoTDeviceBO();
|
||||
BeanUtil.copyProperties(ioTDevice, ioTDeviceBO);
|
||||
// 查询网关产品信息
|
||||
if (StrUtil.isNotBlank(ioTDeviceBO.getGwProductKey())) {
|
||||
IoTDevice parentDevice =
|
||||
iIotDeviceService.selectDeviceByDeviceId(ioTDevice.getGwProductKey());
|
||||
iIotDeviceService.selectIoTDevice(
|
||||
ioTDeviceBO.getGwProductKey(), ioTDevice.getExtDeviceId());
|
||||
if (ObjectUtil.isNotNull(parentDevice)) {
|
||||
ioTDeviceBO.setParentName(
|
||||
ioTDeviceBO.setGwDeviceInfo(
|
||||
parentDevice.getDeviceId() + "(" + parentDevice.getDeviceName() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
+162
-145
@@ -20,16 +20,22 @@ import cn.universal.admin.common.annotation.Log;
|
||||
import cn.universal.admin.common.enums.BusinessType;
|
||||
import cn.universal.admin.common.utils.SecurityUtils;
|
||||
import cn.universal.admin.network.service.INetworkService;
|
||||
import cn.universal.admin.platform.dto.ConnectionInfoDTO;
|
||||
import cn.universal.admin.platform.service.ConnectionInfoService;
|
||||
import cn.universal.admin.platform.service.IIoTDeviceService;
|
||||
import cn.universal.admin.platform.service.IIoTProductService;
|
||||
import cn.universal.admin.platform.service.impl.IoTProductServiceImpl;
|
||||
import cn.universal.admin.system.service.ISysDictTypeService;
|
||||
import cn.universal.admin.system.service.IoTDeviceProtocolService;
|
||||
import cn.universal.admin.system.web.BaseController;
|
||||
import cn.universal.common.constant.IoTConstant;
|
||||
import cn.universal.common.constant.IoTConstant.ProtocolModule;
|
||||
import cn.universal.common.constant.IoTConstant.TcpFlushType;
|
||||
import cn.universal.common.event.EventTopics;
|
||||
import cn.universal.common.event.processer.EventPublisher;
|
||||
import cn.universal.common.exception.IoTException;
|
||||
import cn.universal.core.service.IoTDownlFactory;
|
||||
import cn.universal.ossm.service.ISysOssService;
|
||||
import cn.universal.persistence.entity.IoTDevice;
|
||||
import cn.universal.persistence.entity.IoTDeviceEvents;
|
||||
import cn.universal.persistence.entity.IoTDeviceFunction;
|
||||
@@ -55,7 +61,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -77,29 +82,20 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
@RequestMapping("/admin/v1/product")
|
||||
public class IoTProductController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IIoTProductService devProductService;
|
||||
@Autowired
|
||||
private IIoTDeviceService iIotDeviceService;
|
||||
@Autowired
|
||||
private ISysDictTypeService dictTypeService;
|
||||
@Resource
|
||||
private INetworkService iNetworkService;
|
||||
@Resource
|
||||
private IoTDeviceProtocolService ioTDeviceProtocolService;
|
||||
@Resource
|
||||
private IoTProductMapper ioTProductMapper;
|
||||
@Autowired
|
||||
private IoTProductServiceImpl ioTProductServiceImpl;
|
||||
@Autowired
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
@Autowired private IIoTProductService devProductService;
|
||||
@Autowired private IIoTDeviceService iIotDeviceService;
|
||||
@Autowired private ISysDictTypeService dictTypeService;
|
||||
@Resource private INetworkService iNetworkService;
|
||||
@Resource private IoTDeviceProtocolService ioTDeviceProtocolService;
|
||||
@Resource private IoTProductMapper ioTProductMapper;
|
||||
@Autowired private IoTProductServiceImpl ioTProductServiceImpl;
|
||||
@Autowired private EventPublisher eventPublisher;
|
||||
@Autowired private ISysOssService iSysOssService;
|
||||
@Autowired private ConnectionInfoService connectionInfoService;
|
||||
|
||||
/**
|
||||
* 查询设备产品列表
|
||||
*/
|
||||
/** 查询设备产品列表 */
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(IoTProductQuery query) {
|
||||
// 只能看自己设备,除非是特殊设置和超管
|
||||
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
if (!iotUser.viewAllProduct()) {
|
||||
query.setSelf(true);
|
||||
@@ -118,20 +114,21 @@ public class IoTProductController extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品详情通过 ProductKey
|
||||
*/
|
||||
/** 获取产品详情通过 ProductKey */
|
||||
@GetMapping("/get/pro/{key}")
|
||||
public AjaxResult<IoTProduct> getProByKey(@PathVariable("key") String key) {
|
||||
return devProductService.selectDevProductByKey(key);
|
||||
return devProductService.selectIoTProductByKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备产品列表
|
||||
*/
|
||||
/** 获取网关绑定的子产品列表 */
|
||||
@GetMapping("/gateway/subProducts/{key}")
|
||||
public AjaxResult<List<IoTProduct>> gatewaySubProducts(@PathVariable("key") String gwProductKey) {
|
||||
return devProductService.selectGatewaySubProductsByKey(gwProductKey);
|
||||
}
|
||||
|
||||
/** 查询设备产品列表 */
|
||||
@GetMapping("/v2/list")
|
||||
public TableDataInfo v2List(IoTProductQuery query) {
|
||||
// 只能看自己设备,除非是特殊设置和超管
|
||||
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
if (!iotUser.viewAllProduct()) {
|
||||
query.setSelf(true);
|
||||
@@ -150,12 +147,10 @@ public class IoTProductController extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备产品列表
|
||||
*/
|
||||
/** 查询设备产品列表 */
|
||||
@GetMapping("/v3/list")
|
||||
public TableDataInfo v3List(IoTProductQuery query) {
|
||||
// 只能看自己设备,除非是特殊设置和超管
|
||||
//
|
||||
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
if (!iotUser.viewAllProduct()) {
|
||||
query.setSelf(true);
|
||||
@@ -175,12 +170,10 @@ public class IoTProductController extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备产品列表
|
||||
*/
|
||||
/** 查询设备产品列表 */
|
||||
@GetMapping("/v4/list")
|
||||
public TableDataInfo v4List(IoTProductQuery query) {
|
||||
// 只能看自己设备,除非是特殊设置和超管
|
||||
//
|
||||
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
if (!iotUser.viewAllProduct()) {
|
||||
query.setSelf(true);
|
||||
@@ -200,70 +193,47 @@ public class IoTProductController extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有设备产品列表
|
||||
*/
|
||||
/** 查询所有设备产品列表 */
|
||||
@GetMapping("/all/list")
|
||||
public TableDataInfo v3List() {
|
||||
List<IoTProductVO> list = devProductService.selectDevProductAllList();
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 物模型新增内容
|
||||
*/
|
||||
/** 物模型新增内容 */
|
||||
@PostMapping("/metadata/add")
|
||||
@Log(title = "物模型新增内容", businessType = BusinessType.INSERT)
|
||||
public AjaxResult<Void> metadataAdd(@RequestBody IoTProductBO ioTProductBO) {
|
||||
return toAjax(devProductService.insertMetadata(ioTProductBO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 物模型修改内容
|
||||
*/
|
||||
/** 物模型修改内容 */
|
||||
@PostMapping("/metadata/update")
|
||||
@Log(title = "物模型修改内容", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult<Void> metadataUpdate(@RequestBody IoTProductBO ioTProductBO) {
|
||||
return toAjax(devProductService.updateMetadata(ioTProductBO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 物模型删除内容
|
||||
*/
|
||||
/** 物模型删除内容 */
|
||||
@PostMapping("/metadata/delete")
|
||||
@Log(title = "物模型删除内容", businessType = BusinessType.DELETE)
|
||||
public AjaxResult<Void> metadataDelete(@RequestBody IoTProductBO ioTProductBO) {
|
||||
return toAjax(devProductService.deleteMetadata(ioTProductBO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 物模型查询内容
|
||||
*/
|
||||
/** 物模型查询内容 */
|
||||
@PostMapping("/metadata/get")
|
||||
public AjaxResult<IoTProductBO> metadataGet(@RequestBody IoTProductBO ioTProductBO) {
|
||||
return AjaxResult.success(devProductService.getMetadata(ioTProductBO));
|
||||
}
|
||||
|
||||
/** 导出设备产品列表 */
|
||||
// @PostMapping("/export")
|
||||
// public void export(HttpServletResponse response, IoTProduct ioTProduct)
|
||||
// {
|
||||
// List<IoTProduct> list = devProductService.selectDevProductList(ioTProduct);
|
||||
// ExcelUtil<IoTProduct> util = new ExcelUtil<IoTProduct>(IoTProduct.class);
|
||||
// util.exportExcel(response, list, "设备产品数据");
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取设备产品详细信息
|
||||
*/
|
||||
/** 获取设备产品详细信息 */
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return AjaxResult.success(devProductService.selectDevProductById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询可绑定网关列表
|
||||
*/
|
||||
/** 查询可绑定网关列表 */
|
||||
@Operation(summary = "查询可绑定网关产品列表")
|
||||
@GetMapping("/gateway/list")
|
||||
public AjaxResult<List<IoTProductVO>> getGatewayList() {
|
||||
@@ -271,20 +241,16 @@ public class IoTProductController extends BaseController {
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询可绑定网关子设备产品列表
|
||||
*/
|
||||
/** 查询可绑定网关子设备产品列表 */
|
||||
@Operation(summary = "查询可绑定网关子设备产品列表")
|
||||
@GetMapping("/subdevice/{productKey}")
|
||||
@GetMapping("/sub/device/{productKey}")
|
||||
public AjaxResult<List<IoTProductVO>> getGatewaySubDeviceList(
|
||||
@PathVariable("productKey") String productKey) {
|
||||
List<IoTProductVO> list = devProductService.getGatewaySubDeviceList(productKey);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询电信公共产品列表
|
||||
*/
|
||||
/** 查询电信公共产品列表 */
|
||||
@PostMapping(value = "/ctwing/pubpro")
|
||||
public AjaxResult getCtwingPubPro(@RequestBody String downRequest) {
|
||||
String creatorId = loginIoTUnionUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
@@ -299,23 +265,27 @@ public class IoTProductController extends BaseController {
|
||||
downProRequest.set("data", data);
|
||||
return AjaxResult.success(
|
||||
IoTDownlFactory.safeInvokeDown(
|
||||
ProtocolModule.ctaiot.name(), "downPro", downProRequest.toString()));
|
||||
ProtocolModule.ctaiot.name(),
|
||||
IoTConstant.DOWN_TO_THIRD_PLATFORM,
|
||||
downProRequest.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增设备产品
|
||||
*/
|
||||
/** 新增设备产品 */
|
||||
@PostMapping
|
||||
@Log(title = "新增产品", businessType = BusinessType.INSERT)
|
||||
public AjaxResult add(@RequestBody IoTProduct ioTProduct) {
|
||||
String unionId = loginIoTUnionUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
ioTProduct.setCreatorId(unionId);
|
||||
// 发布产品配置更新事件
|
||||
Map<String, Object> eventData = new HashMap<>();
|
||||
eventData.put("type", "product");
|
||||
eventData.put("productKey", ioTProduct.getProductKey());
|
||||
eventData.put("operation", "ADD");
|
||||
eventPublisher.publishEvent(EventTopics.PRODUCT_CONFIG_UPDATED, eventData);
|
||||
return toAjax(devProductService.insertDevProduct(ioTProduct));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增设备产品NB
|
||||
*/
|
||||
/** 新增设备产品NB */
|
||||
@PostMapping(value = "/nb")
|
||||
@Log(title = "新增产品NB", businessType = BusinessType.INSERT)
|
||||
public AjaxResult addNb(@RequestBody String downRequest) {
|
||||
@@ -343,12 +313,12 @@ public class IoTProductController extends BaseController {
|
||||
downProRequest.set("data", data);
|
||||
return AjaxResult.success(
|
||||
IoTDownlFactory.safeInvokeDown(
|
||||
ProtocolModule.ctaiot.name(), "downPro", downProRequest.toString()));
|
||||
ProtocolModule.ctaiot.name(),
|
||||
IoTConstant.DOWN_TO_THIRD_PLATFORM,
|
||||
downProRequest.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增电信公共产品
|
||||
*/
|
||||
/** 新增电信公共产品 */
|
||||
@PostMapping(value = "/ctwing/pubproadd")
|
||||
@Log(title = "新增电信公共产品", businessType = BusinessType.INSERT)
|
||||
public AjaxResult addCtwingPubPro(@RequestBody String downRequest) {
|
||||
@@ -367,12 +337,12 @@ public class IoTProductController extends BaseController {
|
||||
downProRequest.set("data", data);
|
||||
return AjaxResult.success(
|
||||
IoTDownlFactory.safeInvokeDown(
|
||||
ProtocolModule.ctaiot.name(), "downPro", downProRequest.toString()));
|
||||
ProtocolModule.ctaiot.name(),
|
||||
IoTConstant.DOWN_TO_THIRD_PLATFORM,
|
||||
downProRequest.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改设备产品
|
||||
*/
|
||||
/** 修改设备产品 */
|
||||
@PostMapping(value = "/updateNetworkUnionId")
|
||||
@Log(title = "修改网络组件", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult editNetwork(@RequestBody IoTProductBO ioTProductBO) {
|
||||
@@ -387,9 +357,7 @@ public class IoTProductController extends BaseController {
|
||||
ioTProductBO.getId(), ioTProductBO.getNetworkUnionId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 子设备绑定网关
|
||||
*/
|
||||
/** 子设备绑定网关 */
|
||||
@Operation(summary = "子设备绑定网关")
|
||||
@PutMapping("/gateway")
|
||||
@Log(title = "子设备绑定网关", businessType = BusinessType.UPDATE)
|
||||
@@ -407,9 +375,7 @@ public class IoTProductController extends BaseController {
|
||||
return toAjax(devProductService.updateDevProduct(productVO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改设备产品
|
||||
*/
|
||||
/** 修改设备产品 */
|
||||
@PutMapping
|
||||
@Log(title = "修改设备产品", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult edit(@RequestBody IoTProductBO ioTProductBO) {
|
||||
@@ -434,42 +400,45 @@ public class IoTProductController extends BaseController {
|
||||
downProRequest.set("productKey", ioTProductBO.getProductKey());
|
||||
return AjaxResult.success(
|
||||
IoTDownlFactory.safeInvokeDown(
|
||||
ProtocolModule.ctaiot.name(), "downPro", downProRequest.toString()));
|
||||
ProtocolModule.ctaiot.name(),
|
||||
IoTConstant.DOWN_TO_THIRD_PLATFORM,
|
||||
downProRequest.toString()));
|
||||
}
|
||||
IoTProduct ioTProduct = BeanUtil.toBean(ioTProductBO, IoTProduct.class);
|
||||
return toAjax(devProductService.updateDevProduct(ioTProduct));
|
||||
int result = devProductService.updateDevProduct(ioTProduct);
|
||||
if (result > 0) {
|
||||
// 发布产品配置更新事件
|
||||
Map<String, Object> eventData = new HashMap<>();
|
||||
eventData.put("type", "product");
|
||||
eventData.put("productKey", ioTProduct.getProductKey());
|
||||
eventData.put("operation", "UPDATE");
|
||||
eventPublisher.publishEvent(EventTopics.PRODUCT_CONFIG_UPDATED, eventData);
|
||||
}
|
||||
return toAjax(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改产品配置信息
|
||||
*/
|
||||
/** 修改产品配置信息 */
|
||||
@PutMapping("/config")
|
||||
@Log(title = "修改产品配置信息", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult editConfig(@RequestBody IoTProductVO devProduct) {
|
||||
return toAjax(devProductService.updateDevProductConfig(devProduct));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改产品其他配置信息
|
||||
*/
|
||||
/** 修改产品其他配置信息 */
|
||||
@PutMapping("/otherConfig")
|
||||
@Log(title = "修改产品其他配置信息", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult editOtherConfig(@RequestBody String otherConfig) {
|
||||
return toAjax(devProductService.updateDevProductOtherConfig(otherConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改产品存储策略
|
||||
*/
|
||||
/** 修改产品存储策略 */
|
||||
@PutMapping("/storeConfig")
|
||||
@Log(title = "修改产品存储策略", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult editOtherConfig(@RequestBody IoTProductVO devProduct) {
|
||||
return toAjax(devProductService.updateDevProductStoreConfig(devProduct));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除设备产品
|
||||
*/
|
||||
/** 删除设备产品 */
|
||||
@DeleteMapping("/{ids}")
|
||||
@Log(title = "删除设备产品", businessType = BusinessType.DELETE)
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
@@ -480,7 +449,7 @@ public class IoTProductController extends BaseController {
|
||||
throw new IoTException("没有该产品");
|
||||
}
|
||||
if (!iotUser.isAdmin() && !ioTProduct.getCreatorId().equals(iotUser.getUnionId())) {
|
||||
throw new IoTException("您没有权限操作此产品!");
|
||||
throw new IoTException("没有产品权限");
|
||||
}
|
||||
IoTDevice ioTDevice = IoTDevice.builder().productKey(ioTProduct.getProductKey()).build();
|
||||
List<IoTDevice> ioTDeviceList =
|
||||
@@ -501,7 +470,9 @@ public class IoTProductController extends BaseController {
|
||||
|
||||
return AjaxResult.success(
|
||||
IoTDownlFactory.safeInvokeDown(
|
||||
ProtocolModule.ctaiot.name(), "downPro", downProRequest.toString()));
|
||||
ProtocolModule.ctaiot.name(),
|
||||
IoTConstant.DOWN_TO_THIRD_PLATFORM,
|
||||
downProRequest.toString()));
|
||||
}
|
||||
// tcp产品删除时同时删除network表
|
||||
if (ProtocolModule.tcp.name().equals(ioTProduct.getThirdPlatform())) {
|
||||
@@ -512,22 +483,25 @@ public class IoTProductController extends BaseController {
|
||||
}
|
||||
// 删除协议
|
||||
ioTDeviceProtocolService.deleteDevProtocolById(ioTProduct.getProductKey());
|
||||
|
||||
// 发布产品删除事件
|
||||
Map<String, Object> eventData = new HashMap<>();
|
||||
eventData.put("type", "product");
|
||||
eventData.put("productKey", ioTProduct.getProductKey());
|
||||
eventData.put("operation", "DELETE");
|
||||
eventPublisher.publishEvent(EventTopics.PRODUCT_CONFIG_UPDATED, eventData);
|
||||
}
|
||||
return toAjax(devProductService.deleteDevProductByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备产品物模型属性列表
|
||||
*/
|
||||
/** 查询设备产品物模型属性列表 */
|
||||
@GetMapping("/properties/{id}")
|
||||
public AjaxResult getPropertiesList(@PathVariable("id") String id) {
|
||||
List<IoTDeviceProperties> list = devProductService.selectDevProperties(id);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备产品物模型属性列表(功能下发属性)
|
||||
*/
|
||||
/** 查询设备产品物模型属性列表(功能下发属性) */
|
||||
@GetMapping("/functionProperties/{id}")
|
||||
public AjaxResult getFunctionPropertiesList(@PathVariable("id") String id) {
|
||||
List<IoTDeviceProperties> list = devProductService.selectDevProperties(id);
|
||||
@@ -535,7 +509,8 @@ public class IoTProductController extends BaseController {
|
||||
List<IoTDeviceProperties> dataRw =
|
||||
list.stream().filter((item) -> "rw".equals(item.getMode())).collect(Collectors.toList());
|
||||
// 获取设备公共字段
|
||||
List<SysDictData> data = dictTypeService.selectDictDataByType("device_common_property");
|
||||
List<SysDictData> data =
|
||||
dictTypeService.selectDictDataByType(IoTConstant.DEVICE_SHADOW_CUSTOMIZED_PROPERTY);
|
||||
// 根据公共字段过滤
|
||||
if (Validator.isNotNull(data)) {
|
||||
for (SysDictData datum : data) {
|
||||
@@ -558,27 +533,21 @@ public class IoTProductController extends BaseController {
|
||||
return AjaxResult.success(dataRw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备产品物模型事件列表
|
||||
*/
|
||||
/** 查询设备产品物模型事件列表 */
|
||||
@GetMapping("/events/{id}")
|
||||
public AjaxResult getEventsList(@PathVariable("id") String id) {
|
||||
List<IoTDeviceEvents> list = devProductService.selectDevEvents(id);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备产品物模型方法列表
|
||||
*/
|
||||
/** 查询设备产品物模型方法列表 */
|
||||
@GetMapping("/functions/{id}")
|
||||
public AjaxResult getFunctionsList(@PathVariable("id") String id) {
|
||||
List<IoTDeviceFunction> list = devProductService.selectDevFunctions(id);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据产品key查model配置
|
||||
*/
|
||||
/** 根据产品key查model配置 */
|
||||
@GetMapping("/model/{id}")
|
||||
public AjaxResult getmodel(@PathVariable("id") String id) {
|
||||
IoTDeviceModelVO ioTDeviceModelVO = devProductService.getModelByProductKey(id);
|
||||
@@ -590,7 +559,7 @@ public class IoTProductController extends BaseController {
|
||||
return AjaxResult.success(devProductService.selectMetadataByDevId(devId));
|
||||
}
|
||||
|
||||
@GetMapping("/devnumber")
|
||||
@GetMapping("/device/count")
|
||||
public AjaxResult countDevNumberByProductKey() {
|
||||
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
Map<String, Integer> products =
|
||||
@@ -599,13 +568,11 @@ public class IoTProductController extends BaseController {
|
||||
return AjaxResult.success(products);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出设备产品列表
|
||||
*/
|
||||
/** 导出设备产品列表 */
|
||||
@PostMapping("/export")
|
||||
@Log(title = "产品导出", businessType = BusinessType.EXPORT)
|
||||
public void export(HttpServletResponse response, IoTProductQuery query) {
|
||||
// 只能看自己设备,除非是特殊设置和超管
|
||||
//
|
||||
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
query.setSelf(!iotUser.isAdmin());
|
||||
if (query.isSelf()) {
|
||||
@@ -646,15 +613,13 @@ public class IoTProductController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入产品
|
||||
*/
|
||||
/** 批量导入产品 */
|
||||
@PostMapping("/import")
|
||||
@Log(title = "产品批量导入", businessType = BusinessType.IMPORT)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AjaxResult<Void> importProduct(MultipartFile file) throws Exception {
|
||||
// 模板
|
||||
// 只能看自己设备,除非是特殊设置和超管
|
||||
//
|
||||
String unionId = loginIoTUnionUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
try {
|
||||
// 读取JSON文件内容
|
||||
@@ -675,9 +640,41 @@ public class IoTProductController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载导入模版
|
||||
*/
|
||||
/** 上传产品图片并保存到产品信息 */
|
||||
@Operation(summary = "上传产品图片")
|
||||
@PostMapping("/uploadImage")
|
||||
@Log(title = "上传产品图片", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult<Map<String, String>> uploadProductImage(
|
||||
@RequestParam("id") String id, @RequestParam("file") MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new IoTException("上传文件不能为空");
|
||||
}
|
||||
IoTProductVO product = devProductService.selectDevProductById(id);
|
||||
if (product == null) {
|
||||
throw new IoTException("产品不存在");
|
||||
}
|
||||
String unionId = loginIoTUnionUser(SecurityUtils.getUnionId()).getUnionId();
|
||||
// 上传到 OSS,沿用系统统一上传逻辑
|
||||
var oss = iSysOssService.upload(file, unionId);
|
||||
String url = oss.getUrl();
|
||||
|
||||
// 更新产品 photoUrl 字段(保持前端期望结构)
|
||||
IoTProduct update = new IoTProduct();
|
||||
update.setId(product.getId());
|
||||
JSONObject photo = new JSONObject();
|
||||
photo.set("img", url);
|
||||
photo.set("detail", "");
|
||||
update.setPhotoUrl(photo.toString());
|
||||
devProductService.updateDevProduct(update);
|
||||
|
||||
Map<String, String> data = new HashMap<>(2);
|
||||
data.put("url", url);
|
||||
String name = oss.getOriginalName();
|
||||
data.put("fileName", name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf(".")));
|
||||
return AjaxResult.success(data);
|
||||
}
|
||||
|
||||
/** 下载导入模版 */
|
||||
@PostMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) {
|
||||
List<IoTProductImportBO> list = new ArrayList<>();
|
||||
@@ -723,9 +720,7 @@ public class IoTProductController extends BaseController {
|
||||
return getDataTable(maps);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定证书到产品
|
||||
*/
|
||||
/** 绑定证书到产品 */
|
||||
@PostMapping("/bindCertificate")
|
||||
@Log(title = "绑定证书", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult bindCertificate(@RequestParam String productKey, @RequestParam String sslKey) {
|
||||
@@ -733,13 +728,35 @@ public class IoTProductController extends BaseController {
|
||||
return toAjax(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑证书
|
||||
*/
|
||||
/** 解绑证书 */
|
||||
@PostMapping("/unbindCertificate")
|
||||
@Log(title = "解绑证书", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult unbindCertificate(@RequestParam String productKey) {
|
||||
int result = devProductService.unbindCertificate(productKey);
|
||||
return toAjax(result);
|
||||
}
|
||||
|
||||
/** 查看连接信息 */
|
||||
@PostMapping("/connect/info")
|
||||
@Log(title = "查看连接信息", businessType = BusinessType.OTHER)
|
||||
public AjaxResult connectInfo(@RequestParam String productKey) {
|
||||
try {
|
||||
ConnectionInfoDTO connectionInfo = connectionInfoService.getConnectionInfo(productKey);
|
||||
return AjaxResult.success(connectionInfo);
|
||||
} catch (Exception e) {
|
||||
return AjaxResult.error("获取连接信息失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** 查看MQTT密码 */
|
||||
@PostMapping("/connect/mqtt/password")
|
||||
@Log(title = "查看连接信息密码", businessType = BusinessType.GRANT)
|
||||
public AjaxResult connectInfoPassword(@RequestParam String productKey) {
|
||||
try {
|
||||
ConnectionInfoDTO passwordInfo = connectionInfoService.getMqttPasswordInfo(productKey);
|
||||
return AjaxResult.success(passwordInfo);
|
||||
} catch (Exception e) {
|
||||
return AjaxResult.error("获取密码信息失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+33
-11
@@ -16,11 +16,12 @@ import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import cn.hutool.http.Header;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.universal.admin.common.annotation.Log;
|
||||
import cn.universal.admin.common.enums.BusinessType;
|
||||
@@ -137,6 +138,28 @@ public class IoTUserAppController extends BaseController {
|
||||
util.exportExcel(response, list, "用户应用信息数据");
|
||||
}
|
||||
|
||||
/** 获取用户应用信息详细信息 */
|
||||
@Operation(summary = "启用推送")
|
||||
@PostMapping(value = "/{appUniqueId}/{pushType}/{enable}")
|
||||
public AjaxResult<Void> enableOrDisablePush(
|
||||
@PathVariable("appUniqueId") String appUniqueId,
|
||||
@PathVariable("pushType") String pushType,
|
||||
@PathVariable("enable") boolean enable) {
|
||||
IoTUserApplication application =
|
||||
iotUserApplicationService.selectIotUserApplicationById(appUniqueId);
|
||||
IoTUser user = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
if (!user.isAdmin()
|
||||
&& ObjectUtil.isNotEmpty(application)
|
||||
&& !application.getUnionId().equals(user.getUnionId())) {
|
||||
throw new IoTException("你无权操作");
|
||||
}
|
||||
boolean flag = iotUserApplicationService.enableOrDisablePushCfg(appUniqueId, pushType, enable);
|
||||
if (flag) {
|
||||
return AjaxResult.success();
|
||||
}
|
||||
return AjaxResult.error("失败");
|
||||
}
|
||||
|
||||
/** 获取用户应用信息详细信息 */
|
||||
@Operation(summary = "获取用户应用信息详细信息")
|
||||
@GetMapping(value = "/{appUniqueId}")
|
||||
@@ -198,21 +221,21 @@ public class IoTUserAppController extends BaseController {
|
||||
@Transactional
|
||||
@Log(title = "重置密钥", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult<Void> resetSecret(@RequestBody IoTUserApplication iotUserApplication) {
|
||||
IoTUserApplication oldapplication =
|
||||
iotUserApplicationService.selectIotUserApplicationById(iotUserApplication.getAppUniqueId());
|
||||
IoTUser user = loginIoTUnionUser(SecurityUtils.getUnionId());
|
||||
|
||||
// 权限检查
|
||||
IoTUserApplication oldApplication =
|
||||
iotUserApplicationService.selectIotUserApplicationById(iotUserApplication.getAppUniqueId());
|
||||
if (!user.isAdmin()
|
||||
&& ObjectUtil.isNotEmpty(oldapplication)
|
||||
&& !oldapplication.getUnionId().equals(user.getUnionId())) {
|
||||
&& ObjectUtil.isNotEmpty(oldApplication)
|
||||
&& !oldApplication.getUnionId().equals(user.getUnionId())) {
|
||||
throw new IoTException("你无权操作");
|
||||
}
|
||||
// iotUserApplication.setAppId(RandomUtil.randomString(16));
|
||||
iotUserApplication.setAppSecret(RandomUtil.randomString(32));
|
||||
iotUserApplication.setUnionId(user.getUnionId());
|
||||
if (iotUserApplicationService.updateIotUserApplication(iotUserApplication) == 0) {
|
||||
// 调用service层方法完成密钥重置和MQTT配置同步
|
||||
if (!iotUserApplicationService.resetAppSecretAndSyncMqtt(
|
||||
iotUserApplication.getAppUniqueId(), user.getUnionId())) {
|
||||
throw new IoTException("应用密钥重置失败");
|
||||
}
|
||||
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@@ -238,7 +261,6 @@ public class IoTUserAppController extends BaseController {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("message", "success");
|
||||
iotUserApplication.setUnionId(app.getUnionId());
|
||||
iotUserApplication.setUpTopic(app.getUnionId() + StrUtil.C_SLASH + app.getAppId());
|
||||
iotUserApplicationService.updateIotUserApplication(iotUserApplication);
|
||||
return AjaxResult.success(map);
|
||||
}
|
||||
|
||||
+11
@@ -67,4 +67,15 @@ public interface IIoTUserApplicationService {
|
||||
int deleteIotUserApplicationById(String appUniqueId);
|
||||
|
||||
List<IoTUserApplicationVO> selectApplicationList(IoTUserApplication application, IoTUser iotUser);
|
||||
|
||||
boolean enableOrDisablePushCfg(String appUniqueId, String pushType, boolean isEnable);
|
||||
|
||||
/**
|
||||
* 重置应用密钥并同步更新MQTT配置
|
||||
*
|
||||
* @param appUniqueId 应用唯一标识
|
||||
* @param unionId 用户唯一标识
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean resetAppSecretAndSyncMqtt(String appUniqueId, String unionId);
|
||||
}
|
||||
|
||||
+120
@@ -13,6 +13,9 @@
|
||||
package cn.universal.admin.system.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.universal.admin.common.service.BaseServiceImpl;
|
||||
import cn.universal.admin.common.utils.SecurityUtils;
|
||||
import cn.universal.admin.system.service.IIoTUserApplicationService;
|
||||
@@ -28,9 +31,12 @@ import cn.universal.persistence.mapper.OauthClientDetailsMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tk.mybatis.mapper.entity.Example;
|
||||
|
||||
/**
|
||||
@@ -39,6 +45,7 @@ import tk.mybatis.mapper.entity.Example;
|
||||
* @since 2025-12-30
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class IoTUserApplicationServiceImpl extends BaseServiceImpl
|
||||
implements IIoTUserApplicationService {
|
||||
|
||||
@@ -47,6 +54,12 @@ public class IoTUserApplicationServiceImpl extends BaseServiceImpl
|
||||
|
||||
@Resource private OauthClientDetailsMapper oauthClientDetailsMapper;
|
||||
|
||||
@Value("${mqtt.cfg.enable:true}")
|
||||
private boolean sysMqttEnabled;
|
||||
|
||||
@Value("${mqtt.cfg.host:tcp://localhost:1883}")
|
||||
private String sysMqttHost;
|
||||
|
||||
@Override
|
||||
public boolean EnDisableIoTUser(String unionId, boolean isEnable) {
|
||||
List<IoTUserApplication> select =
|
||||
@@ -212,4 +225,111 @@ public class IoTUserApplicationServiceImpl extends BaseServiceImpl
|
||||
application.setUnionId(iotUser.isAdmin() ? null : iotUser.getUnionId());
|
||||
return iotUserApplicationMapper.selectApplicationList(application);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableOrDisablePushCfg(String appUniqueId, String pushType, boolean isEnable) {
|
||||
IoTUserApplication application =
|
||||
iotUserApplicationMapper.selectOne(
|
||||
IoTUserApplication.builder().appUniqueId(appUniqueId).build());
|
||||
if (application == null) {
|
||||
return false;
|
||||
}
|
||||
// 获取当前推送配置
|
||||
String pushCfgStr = application.getCfg();
|
||||
JSONObject pushCfg;
|
||||
if (StrUtil.isBlank(pushCfgStr)) {
|
||||
pushCfg = new JSONObject();
|
||||
} else {
|
||||
pushCfg = JSONUtil.parseObj(pushCfgStr);
|
||||
}
|
||||
|
||||
switch (pushType) {
|
||||
case "mqtt":
|
||||
if (isEnable) {
|
||||
// MQTT启用:设置url为sysMqttHost、support为true、enable为true
|
||||
// password为app_secret、username为app_id
|
||||
JSONObject mqttConfig = new JSONObject();
|
||||
mqttConfig.set("enable", true);
|
||||
mqttConfig.set("support", true);
|
||||
mqttConfig.set("url", sysMqttHost);
|
||||
mqttConfig.set("password", application.getAppSecret());
|
||||
mqttConfig.set("username", application.getAppId());
|
||||
mqttConfig.set("clientId", application.getAppId());
|
||||
|
||||
pushCfg.set("mqtt", mqttConfig);
|
||||
} else {
|
||||
// MQTT禁用:只设置enable为false
|
||||
if (pushCfg.containsKey("mqtt")) {
|
||||
JSONObject mqttConfig = pushCfg.getJSONObject("mqtt");
|
||||
mqttConfig.set("enable", false);
|
||||
pushCfg.set("mqtt", mqttConfig);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "http":
|
||||
if (isEnable) {
|
||||
// HTTP启用:设置enable和support为true
|
||||
JSONObject httpConfig = pushCfg.getJSONObject("http");
|
||||
httpConfig.set("enable", true);
|
||||
httpConfig.set("support", true);
|
||||
pushCfg.set("http", httpConfig);
|
||||
} else {
|
||||
// HTTP禁用:设置enable为false
|
||||
if (pushCfg.containsKey("http")) {
|
||||
JSONObject httpConfig = pushCfg.getJSONObject("http");
|
||||
httpConfig.set("enable", false);
|
||||
pushCfg.set("http", httpConfig);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// 更新推送配置
|
||||
application.setCfg(pushCfg.toString());
|
||||
int result = iotUserApplicationMapper.updateIotUserApplication(application);
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean resetAppSecretAndSyncMqtt(String appUniqueId, String unionId) {
|
||||
// 查询应用信息
|
||||
IoTUserApplication application =
|
||||
iotUserApplicationMapper.selectOne(
|
||||
IoTUserApplication.builder().appUniqueId(appUniqueId).build());
|
||||
|
||||
if (application == null) {
|
||||
return false;
|
||||
}
|
||||
// 生成新的应用密钥
|
||||
String newAppSecret = cn.hutool.core.util.RandomUtil.randomString(32);
|
||||
application.setAppSecret(newAppSecret);
|
||||
|
||||
// 更新应用信息
|
||||
if (iotUserApplicationMapper.updateByPrimaryKeySelective(application) == 0) {
|
||||
return false;
|
||||
}
|
||||
// 检查MQTT是否开启,如果开启则同步更新MQTT配置中的密码
|
||||
String oldCfg = application.getCfg();
|
||||
if (StrUtil.isNotBlank(oldCfg)) {
|
||||
JSONObject cfg = JSONUtil.parseObj(oldCfg);
|
||||
if (cfg.containsKey("mqtt")) {
|
||||
JSONObject mqttConfig = cfg.getJSONObject("mqtt");
|
||||
if (mqttConfig.getBool("enable", false)) {
|
||||
// MQTT已启用,更新密码
|
||||
mqttConfig.set("password", newAppSecret);
|
||||
cfg.set("mqtt", mqttConfig);
|
||||
|
||||
// 更新配置
|
||||
IoTUserApplication updateCfg = new IoTUserApplication();
|
||||
updateCfg.setAppUniqueId(appUniqueId);
|
||||
updateCfg.setCfg(cfg.toString());
|
||||
iotUserApplicationMapper.updateByPrimaryKeySelective(updateCfg);
|
||||
log.info("应用 {} 密钥重置后,MQTT配置密码已同步更新", appUniqueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user