|
|
|
|
@ -51,7 +51,6 @@ import cn.iocoder.yudao.module.iot.framework.mqtt.consumer.IMqttservice;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.util.MapListStatsCalculator;
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
|
@ -62,6 +61,7 @@ import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang.math.NumberUtils;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
|
|
|
|
import org.springframework.dao.DuplicateKeyException;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
@ -1180,36 +1180,156 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void importDeviceAttributeList(List<DeviceAttributeImportExcelVO> list, Boolean updateSupport, Long deviceId) {
|
|
|
|
|
public String importDeviceAttributeList(List<DeviceAttributeImportExcelVO> list, Boolean updateSupport, Long deviceId) {
|
|
|
|
|
// 1.1 参数校验
|
|
|
|
|
if (CollUtil.isEmpty(list)) {
|
|
|
|
|
throw exception(IMPORT_LIST_IS_EMPTY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1.2 查询主单位数据
|
|
|
|
|
QueryWrapper<ErpProductUnitDO> wrapper = new QueryWrapper<>();
|
|
|
|
|
wrapper.eq("primary_flag", "Y");
|
|
|
|
|
List<ErpProductUnitDO> erpProductUnitDOS = productUnitMapper.selectList(wrapper);
|
|
|
|
|
Map<String, List<ErpProductUnitDO>> map = erpProductUnitDOS.stream().filter(Objects::nonNull)
|
|
|
|
|
.collect(Collectors.groupingBy(
|
|
|
|
|
ErpProductUnitDO::getName,
|
|
|
|
|
Collectors.toList()
|
|
|
|
|
));
|
|
|
|
|
List<DeviceContactModelDO> erpDeviceContactDOs = new ArrayList<>();
|
|
|
|
|
list.stream().forEach(importDeviceAttribute -> {
|
|
|
|
|
/* if(importDeviceAttribute.getDataUnit()!=null){
|
|
|
|
|
List<ErpProductUnitDO> erpProductUnitDOS1 = map.get(importDeviceAttribute.getPrimaryName());
|
|
|
|
|
if (CollUtil.isEmpty(erpProductUnitDOS1)) {
|
|
|
|
|
importDeviceAttribute.setPrimaryId(null);
|
|
|
|
|
} else {
|
|
|
|
|
importDeviceAttribute.setPrimaryId(erpProductUnitDOS1.get(0).getId());
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
Set<String> importAttributeCodes = list.stream()
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.map(DeviceAttributeImportExcelVO::getAttributeCode)
|
|
|
|
|
.map(StringUtils::trimToNull)
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
|
|
|
|
|
|
|
|
|
Set<String> existsAttributeCodes = deviceContactModelMapper
|
|
|
|
|
.selectListByDeviceIdAndAttributeCodes(deviceId, importAttributeCodes)
|
|
|
|
|
.stream()
|
|
|
|
|
.map(DeviceContactModelDO::getAttributeCode)
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
|
|
|
|
|
Set<String> acceptedAttributeCodes = new HashSet<>(existsAttributeCodes);
|
|
|
|
|
List<DeviceContactModelDO> insertList = new ArrayList<>(list.size());
|
|
|
|
|
int invalidCount = 0;
|
|
|
|
|
int duplicateCount = 0;
|
|
|
|
|
|
|
|
|
|
for (DeviceAttributeImportExcelVO importDeviceAttribute : list) {
|
|
|
|
|
if (importDeviceAttribute == null) {
|
|
|
|
|
invalidCount++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String attributeCode = StringUtils.trimToNull(importDeviceAttribute.getAttributeCode());
|
|
|
|
|
String attributeName = StringUtils.trimToNull(importDeviceAttribute.getAttributeName());
|
|
|
|
|
if (attributeCode == null || attributeName == null) {
|
|
|
|
|
invalidCount++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
tdengineService.validateColumnName(attributeCode);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
invalidCount++;
|
|
|
|
|
log.warn("Skip invalid imported device attribute column: deviceId={}, attributeCode={}, reason={}",
|
|
|
|
|
deviceId, attributeCode, e.getMessage());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!acceptedAttributeCodes.add(attributeCode)) {
|
|
|
|
|
duplicateCount++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceContactModelDO deviceAttribute = BeanUtils.toBean(importDeviceAttribute, DeviceContactModelDO.class);
|
|
|
|
|
deviceAttribute.setDeviceId(deviceId);
|
|
|
|
|
erpDeviceContactDOs.add(deviceAttribute);
|
|
|
|
|
});
|
|
|
|
|
CollUtil.isNotEmpty(erpDeviceContactDOs);deviceContactModelMapper.insertBatch(erpDeviceContactDOs);
|
|
|
|
|
deviceAttribute.setAttributeCode(attributeCode);
|
|
|
|
|
deviceAttribute.setAttributeName(attributeName);
|
|
|
|
|
insertList.add(deviceAttribute);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImportInsertResult insertResult = insertDeviceAttributes(insertList, existsAttributeCodes);
|
|
|
|
|
duplicateCount += insertResult.getDuplicateCount();
|
|
|
|
|
int tdengineFailureCount = addTdengineColumns(deviceId, insertResult.getInsertedList());
|
|
|
|
|
|
|
|
|
|
return String.format("\u5bfc\u5165\u5b8c\u6210\uff1a\u6210\u529f%d\u6761\uff0c\u8fc7\u6ee4%d\u6761\uff08\u5df2\u5b58\u5728/\u91cd\u590d%d\u6761\uff0c\u4e0d\u7b26\u5408\u89c4\u5219%d\u6761\uff0c\u63d2\u5165\u5931\u8d25%d\u6761\uff09\uff0cTDengine\u5217\u540c\u6b65\u5931\u8d25%d\u6761",
|
|
|
|
|
insertResult.getInsertedList().size(),
|
|
|
|
|
duplicateCount + invalidCount + insertResult.getFailureCount(),
|
|
|
|
|
duplicateCount,
|
|
|
|
|
invalidCount,
|
|
|
|
|
insertResult.getFailureCount(),
|
|
|
|
|
tdengineFailureCount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ImportInsertResult insertDeviceAttributes(List<DeviceContactModelDO> insertList, Set<String> preExistingAttributeCodes) {
|
|
|
|
|
ImportInsertResult result = new ImportInsertResult();
|
|
|
|
|
if (CollUtil.isEmpty(insertList)) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
deviceContactModelMapper.insertBatch(insertList, 1000);
|
|
|
|
|
result.getInsertedList().addAll(insertList);
|
|
|
|
|
return result;
|
|
|
|
|
} catch (DuplicateKeyException e) {
|
|
|
|
|
log.warn("Batch import device attributes has concurrent duplicates, fallback to row insert: size={}", insertList.size());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.warn("Batch import device attributes failed, fallback to row insert: size={}, reason={}", insertList.size(), e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<String, DeviceContactModelDO> currentAttributeMap = deviceContactModelMapper
|
|
|
|
|
.selectListByDeviceIdAndAttributeCodes(insertList.get(0).getDeviceId(),
|
|
|
|
|
insertList.stream()
|
|
|
|
|
.map(DeviceContactModelDO::getAttributeCode)
|
|
|
|
|
.collect(Collectors.toSet()))
|
|
|
|
|
.stream()
|
|
|
|
|
.filter(item -> !preExistingAttributeCodes.contains(item.getAttributeCode()))
|
|
|
|
|
.collect(Collectors.toMap(DeviceContactModelDO::getAttributeCode, Function.identity(), (first, second) -> first));
|
|
|
|
|
result.getInsertedList().addAll(currentAttributeMap.values());
|
|
|
|
|
|
|
|
|
|
for (DeviceContactModelDO item : insertList) {
|
|
|
|
|
if (currentAttributeMap.containsKey(item.getAttributeCode())) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
deviceContactModelMapper.insert(item);
|
|
|
|
|
result.getInsertedList().add(item);
|
|
|
|
|
} catch (DuplicateKeyException e) {
|
|
|
|
|
result.increaseDuplicateCount();
|
|
|
|
|
log.warn("Skip concurrent duplicate imported device attribute: deviceId={}, attributeCode={}",
|
|
|
|
|
item.getDeviceId(), item.getAttributeCode());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
result.increaseFailureCount();
|
|
|
|
|
log.warn("Imported device attribute insert failed: deviceId={}, attributeCode={}, reason={}",
|
|
|
|
|
item.getDeviceId(), item.getAttributeCode(), e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int addTdengineColumns(Long deviceId, List<DeviceContactModelDO> insertedList) {
|
|
|
|
|
if (CollUtil.isEmpty(insertedList)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tdengineService.AddTDDatabaseColumns(deviceId, insertedList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static class ImportInsertResult {
|
|
|
|
|
private final List<DeviceContactModelDO> insertedList = new ArrayList<>();
|
|
|
|
|
private int duplicateCount;
|
|
|
|
|
private int failureCount;
|
|
|
|
|
|
|
|
|
|
public List<DeviceContactModelDO> getInsertedList() {
|
|
|
|
|
return insertedList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getDuplicateCount() {
|
|
|
|
|
return duplicateCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void increaseDuplicateCount() {
|
|
|
|
|
duplicateCount++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getFailureCount() {
|
|
|
|
|
return failureCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void increaseFailureCount() {
|
|
|
|
|
failureCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|