#修复设备管理的接口和现有的厂家做兼容(sql中修改表名字+字段id)

This commit is contained in:
2026-05-12 10:36:06 +08:00
parent a8bdcad183
commit 38bc68c926
9 changed files with 317 additions and 7 deletions

View File

@@ -26,9 +26,9 @@ import java.util.List;
*/
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "Device", description = "设备对象 iot_device")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonInclude(JsonInclude.Include.ALWAYS)
@Data
@TableName("iot_device")
@TableName(value = "iot_device")
public class Device extends BaseDO {
private static final long serialVersionUID = 1L;
@@ -260,4 +260,8 @@ public class Device extends BaseDO {
@TableField(exist = false)
private DeviceRunningStatusHistory lastRunningStatus;
public DeviceRunningStatusHistory getLastRunningStatus() {
return lastRunningStatus != null ? lastRunningStatus : new DeviceRunningStatusHistory();
}
}

View File

@@ -41,6 +41,8 @@ public class Product extends BaseDO {
private String subscribeTopic;
private Integer deviceType;
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> thingsModels;

View File

@@ -0,0 +1 @@
package com.maibu.core.business.dto;

View File

@@ -19,9 +19,15 @@ public class GlobalMemory {
// orgId - siteId - deviceId
public static ConcurrentHashMap<Long, IoTCommonDevice> unRegisterCommonDeviceMap = new ConcurrentHashMap<>();
// public static ConcurrentHashMap<Long, IoTCommonDevice> unRegisterCommonDeviceMap = new ConcurrentHashMap<>();
//
// public static ConcurrentHashMap<Long, Device> unRegisterDeviceMap = new ConcurrentHashMap<>();
// orgId - siteId - deviceId
public static ConcurrentHashMap<String, IoTCommonDevice> unRegisterCommonDeviceMap = new ConcurrentHashMap<>();
public static ConcurrentHashMap<String, Device> unRegisterDeviceMap = new ConcurrentHashMap<>();
public static ConcurrentHashMap<Long, Device> unRegisterDeviceMap = new ConcurrentHashMap<>();
// key:orgId - siteId
public static ConcurrentHashMap<Long, Map<Long, SiteMemory>> orgAttrs = new ConcurrentHashMap<>();

View File

@@ -64,6 +64,7 @@ public class DeviceController extends BaseController {
@GetMapping("/userDevice")
@PreAuthorize("@ss.hasPermi('iot:device:list')")
public AjaxResult userDevice(Device device) {
return AjaxResult.success(deviceService.selectDeviceList(device));
}

View File

@@ -6,12 +6,14 @@ import com.maibu.core.business.DevicePlan;
import com.maibu.core.business.DeviceRunningStatusHistory;
import com.maibu.core.business.DeviceStatusRecordDTO;
import com.maibu.core.domain.AjaxResult;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.core.enums.DeviceTaskStaus;
import com.maibu.core.redis.RedisCache;
import com.maibu.mapper.DeviceMapper;
import com.maibu.mapper.DevicePlanMapper;
import com.maibu.mapper.DeviceStatusHistoryMapper;
import com.maibu.service.IDeviceService;
import com.maibu.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -86,6 +88,24 @@ public class DeviceServiceImpl implements IDeviceService {
*/
@Override
public List<Device> selectDeviceList(Device device) {
// 从登录上下文获取当前用户
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null) {
String username = loginUser.getUsername();
Long userId = loginUser.getUserId();
// 超级管理员特殊处理
if (!"admin".equals(username)) {
// 非管理员只能看自己租户的数据
if (device.getTenantId() == null) {
device.setTenantId(userId);
}
}
// admin 不设置 tenantId,可以查所有租户
}
List<Device> deviceList = deviceMapper.selectDeviceList(device);
if (!CollectionUtils.isEmpty(deviceList)) {

View File

@@ -75,7 +75,7 @@
d.slave_id,
p.device_type
from iot_device d
left join iot_product p on d.product_id = p.product_id
left join device_product p on d.product_id = p.id
</sql>
<sql id="selectDeviceShortVo">
@@ -132,7 +132,7 @@
'%')
</if>
<if test="tenantId != null ">and d.tenant_id = #{tenantId}</if>
<if test="tenantName != null and tenantName != ''">and d.tenant_name = #{tenantName}</if>
<!-- <if test="tenantName != null and tenantName != ''">and d.tenant_name = #{tenantName}</if>-->
<if test="serialNumber != null and serialNumber != ''">and d.serial_number = #{serialNumber}</if>
<if test="status != null ">and d.status = #{status}</if>
<if test="networkAddress != null and networkAddress != ''">and d.network_address like concat('%',
@@ -231,7 +231,7 @@
p.transport,
p.protocol_code
from iot_device d
left join iot_product p on p.product_id = d.product_id
left join device_product p on p.id = d.product_id
where device_id = #{deviceId}
</select>

View File

@@ -1,7 +1,11 @@
package com.maibu.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.maibu.core.business.IoTCommonDevice;
import com.maibu.core.business.dto.DeviceConfigDTO;
import java.util.List;
/**
* @author jsmbz
@@ -10,4 +14,50 @@ import com.maibu.core.business.IoTCommonDevice;
*/
public interface IotDeviceCommonService extends IService<IoTCommonDevice> {
/**
* 设备录入:连接测试成功后放入未注册缓存
*/
void addDeviceToUnRegisterCache(DeviceConfigDTO deviceDTO) throws Exception;
/**
* 查询未注册设备列表
*/
List<IoTCommonDevice> getUnRegisterDevices();
/**
* 分页查询已注册设备列表
*/
Page<IoTCommonDevice> selectDevicePage(Page<IoTCommonDevice> page, IoTCommonDevice device);
/**
* 根据 SN 查询设备
*/
IoTCommonDevice getBySn(String sn);
/**
* 从未注册缓存注册到组织/场站,并落库
*/
void registerDevice(Long deviceId, Long orgId, Long siteId);
/**
* 编辑设备
* @param deviceDTO
* @return
*/
boolean updateDevice(DeviceConfigDTO deviceDTO);
/**
*
* @param sn
* @return
*/
IoTCommonDevice getFromUnRegisterCache(String sn);
/**
*
* @param cacheDevice
*/
void updateUnRegisterCache(IoTCommonDevice cacheDevice);
}

View File

@@ -1,18 +1,244 @@
package com.maibu.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maibu.core.business.IoTCommonDevice;
import com.maibu.core.business.dto.DeviceConfigDTO;
import com.maibu.mapper.IotDeviceCommonMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.service.IotDeviceCommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* @author jsmbz
* @description 针对表【iot_device_common(通用设备表)】的数据库操作Service实现
* @createDate 2026-05-09 14:38:50
*/
@Slf4j
@Service
public class IotDeviceCommonServiceImpl extends ServiceImpl<IotDeviceCommonMapper, IoTCommonDevice>
implements IotDeviceCommonService {
@Override
public void addDeviceToUnRegisterCache(DeviceConfigDTO deviceDTO) throws Exception {
// 1. 检查 SN 是否已存在(缓存 + 数据库)
if (GlobalMemory.unRegisterCommonDeviceMap.containsKey(deviceDTO.getSn())) {
throw new RuntimeException("设备 SN 已在未注册队列中");
}
IoTCommonDevice dbDevice = this.getBySn(deviceDTO.getSn());
if (dbDevice != null) {
throw new RuntimeException("设备 SN 已录入");
}
// 2. 执行连接测试(根据协议类型)
boolean connectSuccess = testDeviceConnection(deviceDTO);
if (!connectSuccess) {
throw new RuntimeException("设备连接失败,请检查 IP、端口、账号密码");
}
// 3. 连接成功 → 放入未注册缓存
IoTCommonDevice device = new IoTCommonDevice();
device.setDeviceId(deviceDTO.getSn());
device.setDeviceName(deviceDTO.getDeviceName());
device.setProductId(deviceDTO.getProductId());
device.setModelId(deviceDTO.getModelId());
device.setConnectType(deviceDTO.getConnectType());
device.setNetworkIp(deviceDTO.getIp());
device.setRemark(deviceDTO.getRemark());
device.setStatus(1); // 1-未激活
device.setDelFlag(false);
device.setCreateTime(LocalDateTime.now());
// 存入未注册缓存(key 用 SN)
GlobalMemory.unRegisterCommonDeviceMap.put(deviceDTO.getSn(), device);
log.info("设备 {} 已加入未注册缓存", deviceDTO.getSn());
}
@Override
public List<IoTCommonDevice> getUnRegisterDevices() {
return new ArrayList<>(GlobalMemory.unRegisterCommonDeviceMap.values());
}
@Override
public Page<IoTCommonDevice> selectDevicePage(Page<IoTCommonDevice> page, IoTCommonDevice device) {
LambdaQueryWrapper<IoTCommonDevice> wrapper = new LambdaQueryWrapper<>();
if (device.getDeviceName() != null && !device.getDeviceName().isEmpty()) {
wrapper.like(IoTCommonDevice::getDeviceName, device.getDeviceName());
}
if (device.getProductId() != null) {
wrapper.eq(IoTCommonDevice::getProductId, device.getProductId());
}
if (device.getConnectType() != null) {
wrapper.eq(IoTCommonDevice::getConnectType, device.getConnectType());
}
wrapper.eq(IoTCommonDevice::getDelFlag, false);
wrapper.orderByDesc(IoTCommonDevice::getCreateTime);
return this.page(page, wrapper);
}
@Override
public IoTCommonDevice getBySn(String sn) {
LambdaQueryWrapper<IoTCommonDevice> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(IoTCommonDevice::getDeviceId, sn)
.eq(IoTCommonDevice::getDelFlag, false);
return this.getOne(wrapper);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void registerDevice(Long deviceId, Long orgId, Long siteId) {
// TODO: 从未注册缓存取出设备,绑定组织/场站,落库
// 根据具体业务实现
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateDevice(DeviceConfigDTO deviceDTO) {
// 1. 查询设备是否存在
IoTCommonDevice existDevice = this.getById(deviceDTO.getId());
if (existDevice == null) {
throw new RuntimeException("设备不存在");
}
// 2. 判断是否需要重新连接测试(修改了连接信息)
boolean needRetest = false;
if (deviceDTO.getConnectType() != null && !deviceDTO.getConnectType().equals(existDevice.getConnectType())) {
needRetest = true;
}
if (deviceDTO.getIp() != null && !deviceDTO.getIp().equals(existDevice.getNetworkIp())) {
needRetest = true;
}
if (deviceDTO.getPort() != null && !deviceDTO.getPort().equals(existDevice.getPort())) {
needRetest = true;
}
// 3. 如果需要重测,执行连接测试
if (needRetest) {
boolean connectSuccess = testDeviceConnection(deviceDTO);
if (!connectSuccess) {
throw new RuntimeException("新连接配置测试失败,请检查 IP、端口、账号密码");
}
}
// 4. 智能更新:MyBatis-Plus 的 updateById 只会更新非 null 字段
IoTCommonDevice device = new IoTCommonDevice();
BeanUtils.copyProperties(deviceDTO, device);
device.setUpdateTime(LocalDateTime.now());
return this.updateById(device);
}
/**
* 设备连接测试(根据协议类型)
*/
private boolean testDeviceConnection(DeviceConfigDTO deviceDTO) {
switch (deviceDTO.getConnectType()) {
case MQTT:
return testMqttConnection(deviceDTO.getIp(), deviceDTO.getPort(),
deviceDTO.getUsername(), deviceDTO.getPassword());
case ONVIF:
return testOnvifConnection(deviceDTO.getIp(), deviceDTO.getPort(),
deviceDTO.getUsername(), deviceDTO.getPassword());
case RTSP:
return testRtspConnection(deviceDTO.getIp(), deviceDTO.getPort(),
deviceDTO.getUsername(), deviceDTO.getPassword());
default:
throw new RuntimeException("不支持的协议类型");
}
}
@Override
public IoTCommonDevice getFromUnRegisterCache(String sn) {
return GlobalMemory.unRegisterCommonDeviceMap.get(sn);
}
@Override
public void updateUnRegisterCache(IoTCommonDevice device) {
if (device.getDeviceId() == null) {
throw new RuntimeException("设备 ID (SN) 不能为空");
}
// 直接覆盖内存 Map 中的数据
GlobalMemory.unRegisterCommonDeviceMap.put(device.getDeviceId(), device);
log.info("未注册设备 {} 缓存配置已更新", device.getDeviceId());
}
/**
* MQTT 连接测试
*/
private boolean testMqttConnection(String ip, Integer port, String username, String password) {
try {
// TODO: 使用 MQTT 客户端测试连接
// MqttClient client = new MqttClient("tcp://" + ip + ":" + port, "test-" + UUID.randomUUID());
// ...
return true; // 暂时返回 true,后续接入真实 MQTT 库
} catch (Exception e) {
log.error("MQTT 连接测试失败", e);
return false;
}
}
/**
* ONVIF 连接测试
*/
private boolean testOnvifConnection(String ip, Integer port, String username, String password) {
try {
// TODO: 使用 ONVIF 客户端测试连接
return true; // 暂时返回 true
} catch (Exception e) {
log.error("ONVIF 连接测试失败", e);
return false;
}
}
/**
* RTSP 连接测试
*/
private boolean testRtspConnection(String ip, Integer port, String username, String password) {
try {
// TODO: 使用 RTSP 客户端测试连接
return true; // 暂时返回 true
} catch (Exception e) {
log.error("RTSP 连接测试失败", e);
return false;
}
}
}