This commit is contained in:
高云鹏 2025-01-13 17:46:07 +08:00
commit bfcb771437
20 changed files with 282 additions and 179 deletions

View File

@ -20,7 +20,7 @@ if (USE_SQLITE3)
endif ()
endif ()
set (CMAKE_BUILD_TYPE Release)
# set (CMAKE_BUILD_TYPE Release)
option (USE_32BITS "Build 32Bits application?" OFF)
if (USE_32BITS)

View File

@ -2829,10 +2829,12 @@ void CRYDevice::heart_beat(int status)
#endif
jsonValue["linkId"] = linkId;
jsonValue["online"] = (config.processes[i].real_softdog >= PROCESS_WATCHDOG_TIME) ? false : true;
#if 1
jsonValue["real"] = (config.processes[i].real_softdog >= PROCESS_WATCHDOG_TIME) ? false : true;
if ((config.processes[i].state & 0x20) == 0x20) {
jsonValue["ftp"] = (config.processes[i].real_softdog >= PROCESS_WATCHDOG_TIME) ? false : true;
}
#endif
jsonLink.append(jsonValue);
}
}
@ -2853,6 +2855,12 @@ void CRYDevice::heart_beat(int status)
#endif
jsonValue["deviceId"] = deviceId;
jsonValue["online"] = (config.units[i].real_softdog >= UNIT_WATCHDOG_TIME) ? false : true;
#if 0
jsonValue["real"] = (config.units[i].real_softdog >= UNIT_WATCHDOG_TIME) ? false : true;
if ((config.units[i].state & 0x20) == 0x20) {
jsonValue["ftp"] = (config.units[i].real_softdog >= UNIT_WATCHDOG_TIME) ? false : true;
}
#endif
jsonDevice.append(jsonValue);
}
}

View File

@ -1741,14 +1741,7 @@ void CProcess::Destroy(void)
{
m_bRunFlag = FALSE;
char name[16];
memset(name, '\0', sizeof(name));
if (pthread_getname_np(m_pid, name, sizeof(name)) != 0)
{
memset(name, '\0', sizeof(name));
}
vLog(LOG_DEBUG, "waiting for protocol thread [%d,%s] destroy.\n", m_nProcess, (name[0] != '\0') ? name : "unknow");
vLog(LOG_DEBUG, "waiting for protocol thread [%d,%s] destroy.\n", m_nProcess, config.processes[m_nProcess].name);
pthread_join(m_pid, NULL);
int i = 0;
@ -1757,7 +1750,7 @@ void CProcess::Destroy(void)
DestroyItem(i, FALSE);
}
vLog(LOG_DEBUG, "current protocol thread [%d,%s] is destroyed.\n", m_nProcess, (name[0] != '\0') ? name : "unknow");
vLog(LOG_DEBUG, "current protocol thread [%d,%s] is destroyed.\n", m_nProcess, config.processes[m_nProcess].name);
}
BOOLEAN CProcess::Run(void)

View File

@ -703,15 +703,10 @@ CHostADSBFProcess::~CHostADSBFProcess()
fwrite(&m_currentDirStartFileNo, sizeof(LONG), 1, pf);
fclose(pf);
}
char name[16];
memset(name, '\0', sizeof(name));
if (pthread_getname_np(m_cpid, name, sizeof(name)) != 0)
{
memset(name, '\0', sizeof(name));
}
vLog(LOG_DEBUG, "waiting for child thread [%s] destroy.\n", (name[0] != '\0') ? name : "unknow");
vLog(LOG_DEBUG, "waiting for child thread [%s] destroy.\n", (m_cpidName[0] != '\0') ? m_cpidName : "unknow");
pthread_join(m_cpid, NULL);
vLog(LOG_DEBUG, "child protocol thread [%s] is destroyed.\n", (name[0] != '\0') ? name : "unknow");
vLog(LOG_DEBUG, "child protocol thread [%s] is destroyed.\n", (m_cpidName[0] != '\0') ? m_cpidName : "unknow");
}
}
@ -748,6 +743,7 @@ BOOLEAN CHostADSBFProcess::calc(void)
pData = GetUnitYCParamByPoint(uid, n);
if (pData[4] == 1) continue;
registerAddr = MAKEWORD(pData[0], pData[1]);
if (registerAddr <= 0) continue;
if (registerAddr < DATA_BLOCK_BOUNDARY)
{
if (!m_adsDatas[0].inuse) m_adsDatas[0].inuse = TRUE;
@ -775,6 +771,7 @@ BOOLEAN CHostADSBFProcess::calc(void)
pData = GetUnitYMParamByPoint(uid, n);
if (pData[4] == 1) continue;
registerAddr = MAKEWORD(pData[0], pData[1]);
if (registerAddr <= 0) continue;
if (registerAddr < DATA_BLOCK_BOUNDARY)
{
if (!m_adsDatas[0].inuse) m_adsDatas[0].inuse = TRUE;
@ -802,6 +799,7 @@ BOOLEAN CHostADSBFProcess::calc(void)
pData = GetUnitYXParamByPoint(uid, n);
if (pData[4] == 1) continue;
registerAddr = MAKEWORD(pData[0], pData[1]);
if (registerAddr <= 0) continue;
value_type = pData[2];
if (registerAddr < DATA_BLOCK_BOUNDARY)
{
@ -857,14 +855,17 @@ BOOLEAN CHostADSBFProcess::OnPreCreate(int id)
//需要给单元添加一个是否有ftp数据的标识
int uid = GetCurUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
//if (uid < 0 || uid >= UNIT_NUM) return FALSE;
if (m_bHaveFTP) {
if (uid >= 0 && uid < UNIT_NUM)
{
config.units[uid].state |= 0x20; //存在ftp标识
}
config.processes[id].state |= 0x20;
}
calc();
//vLog(LOG_DEBUG, "%s local ip is: %s, netid is: %s, remote ip is: %s, and netid is: %s\n", m_pidName.c_str(), m_localIp.c_str(), m_localNetId.c_str(), m_remoteIp.c_str(), m_remoteNetId.c_str());
vLog(LOG_DEBUG, "%s local ip is: %s, netid is: %s, remote ip is: %s, and netid is: %s\n", m_pidName.c_str(), m_localIp.c_str(), m_localNetId.c_str(), m_remoteIp.c_str(), m_remoteNetId.c_str());
m_turbine = NULL;
m_bRouteAdded = FALSE;
@ -911,9 +912,8 @@ BOOLEAN CHostADSBFProcess::OnPreCreate(int id)
vLog(LOG_ERROR, "ads create ryftp_process error(%d,%s).\n", errno, strerror(errno));
return TRUE;
}
char name[17];
snprintf(name, 16, "%s_ftp", m_pidName.c_str());
pthread_setname_np(m_cpid, name);
snprintf(m_cpidName, 16, "%s_ftp", m_pidName.c_str());
pthread_setname_np(m_cpid, m_cpidName);
pthread_attr_destroy(&attr);
}
@ -1027,10 +1027,11 @@ BOOLEAN CHostADSBFProcess::readFileID()
AdsVariable <DWORD> wFirstFileNoRecoverable {*m_turbine, ".gwFirstFileNoRecoverable"};
//vLog(LOG_DEBUG, "Read back with first value %d\n", (DWORD)wFirstFileNoRecoverable);
#else
WORD wPathInfoInvalid;
WORD wPathInfoInvalid = 1;
myAdsVariable myPathInfoInvalid {*m_turbine, ".gwPathInfoInvalid"};
if (!myPathInfoInvalid.Read(2, &wPathInfoInvalid))
{
vLog(LOG_ERROR, "Read .gwPathInfoInvalid error.\n");
m_bRouteAdded = FALSE;
delete m_turbine;
m_turbine = NULL;
@ -1104,10 +1105,10 @@ BOOLEAN CHostADSBFProcess::readFileID()
}
#endif
m_iv = (WORD)wPathInfoInvalid;
if (m_iv) {
m_iv = (int)wPathInfoInvalid;
if (m_iv == 1) {
vLog(LOG_DEBUG, "路径信息无效\n");
return FALSE;
return TRUE;
}
//当前文件夹路径名
m_currentDirNo = (DWORD)wCurrentFolderNo;

View File

@ -33,6 +33,9 @@ struct myAdsVariable {
{
if (!m_Route.IsConnected()) return FALSE;
uint32_t bytesRead = 0;
if (*m_Handle.get() == 0xffffffff) {
return TRUE;
}
auto error = m_Route.ReadReqEx2(m_IndexGroup,
*m_Handle,
size,
@ -103,8 +106,8 @@ private:
public:
std::string m_pidName;
BOOLEAN m_bHaveFTP; //存在FTP协议
char m_cpidName[16];
//ftp参数信息
char m_user[64];

View File

@ -794,9 +794,9 @@ CHostModbusTcpBFProcess::~CHostModbusTcpBFProcess()
{
memset(name, '\0', sizeof(name));
}
vLog(LOG_DEBUG, "waiting for child thread [%s] destroy.\n", (name[0] != '\0') ? name : "unknow");
vLog(LOG_DEBUG, "waiting for child thread [%s] destroy.\n", (m_cpidName[0] != '\0') ? m_cpidName : "unknow");
pthread_join(m_cpid, NULL);
vLog(LOG_DEBUG, "child protocol thread [%s] is destroyed.\n", (name[0] != '\0') ? name : "unknow");
vLog(LOG_DEBUG, "child protocol thread [%s] is destroyed.\n", (m_cpidName[0] != '\0') ? m_cpidName : "unknow");
}
}
@ -1175,13 +1175,13 @@ BOOLEAN CHostModbusTcpBFProcess::OnPreCreate(int id)
pthread_attr_setstacksize(&attr, MEMERY_1M);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
if (pthread_create(&m_cpid, &attr, ryftp_process, this) < 0) {
if (pthread_create(&m_cpid, &attr, ryftp_process, this) < 0)
{
vLog(LOG_ERROR, "rymodbus create ryftp_process error(%d,%s).\n", errno, strerror(errno));
return TRUE;
}
char name[17];
snprintf(name, 16, "%s_ftp", m_pidName.c_str());
pthread_setname_np(m_cpid, name);
snprintf(m_cpidName, 16, "%s_ftp", m_pidName.c_str());
pthread_setname_np(m_cpid, m_cpidName);
pthread_attr_destroy(&attr);
}

View File

@ -65,6 +65,7 @@ private:
public:
std::string m_pidName;
BOOLEAN m_bHaveFTP; //存在FTP协议
char m_cpidName[16];
//ftp参数信息
char m_user[64];

View File

@ -123,7 +123,10 @@ AdsHandle AdsDevice::GetHandle(const std::string& symbolName) const
if (error || (sizeof(handle) != bytesRead)) {
LOG_ERROR("AdsDevice GetSymbolHandle is failed: " << symbolName << ".");
//throw AdsException(error);
}else{
return {new uint32_t {0xffffffff}, {[](uint32_t){ return 0; }}};
}
else
{
handle = Beckhoff::letoh(handle);
return {new uint32_t {handle}, {std::bind(&AdsDevice::DeleteSymbolHandle, this, std::placeholders::_1)}};
}
@ -137,7 +140,8 @@ AdsHandle AdsDevice::GetHandle(const uint32_t indexGroup,
PAdsNotificationFuncEx callback,
const uint32_t hUser) const
{
if(m_Connected == true){
if (m_Connected == true)
{
uint32_t handle = 0;
auto error = AdsSyncAddDeviceNotificationReqEx(
*m_LocalPort, &m_Addr,
@ -146,10 +150,13 @@ AdsHandle AdsDevice::GetHandle(const uint32_t indexGroup,
callback,
hUser,
&handle);
if (error || !handle) {
if (error || !handle)
{
LOG_WARN("AdsDevice GetNotificationHandle is failed.");
//throw AdsException(error);
}else{
}
else
{
handle = Beckhoff::letoh(handle);
return {new uint32_t {handle}, {std::bind(&AdsDevice::DeleteNotificationHandle, this, std::placeholders::_1)}};
}

View File

@ -32,7 +32,6 @@
<disruptor.version>3.4.4</disruptor.version>
<aviator.version>5.4.3</aviator.version>
<minio.version>8.4.3</minio.version>
<jfreechart.version>1.5.3</jfreechart.version>
</properties>
<dependencies>
@ -217,11 +216,6 @@
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>${jfreechart.version}</version>
</dependency>
</dependencies>
<build>

View File

@ -1,5 +1,6 @@
package com.das.modules.cache.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
@Data
@ -10,6 +11,8 @@ public class IotFieldInfoCache {
private Integer porder;
private Integer highspeed;
private String datatype;
private Integer level;
private String stateDesc;
public boolean isHighSpeed() {
return highspeed.equals(1) && attributeType.equals(138);

View File

@ -1,7 +1,16 @@
package com.das.modules.cache.service;
import com.das.modules.cache.domain.IotFieldInfoCache;
import com.das.modules.equipment.entity.SysIotModel;
import com.das.modules.equipment.entity.SysIotModelField;
public interface IotModelCache {
public boolean isHighSpeed(Long modelId, String attr);
public boolean isLowSpeed(Long modelId, String attr);
public boolean isCalculate(Long modelId, String attr);
void refreshIotFieldCache(SysIotModelField sysIotModelField);
void removeIotFieldCache(Long modelId, String attributeCode);
void refreshIotModelInfoIdMap(SysIotModel sysIotModel);
void removeIotModelInfoIdMap(Long modelId);
IotFieldInfoCache getIotFiledCache(Long modelId,String attr);
}

View File

@ -3,6 +3,8 @@ package com.das.modules.cache.service.impl;
import com.das.modules.cache.domain.IotFieldInfoCache;
import com.das.modules.cache.domain.IotModelInfoCache;
import com.das.modules.cache.service.IotModelCache;
import com.das.modules.equipment.entity.SysIotModel;
import com.das.modules.equipment.entity.SysIotModelField;
import com.das.modules.equipment.mapper.SysIotModelMapper;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
@ -38,6 +40,8 @@ public class IotModelCacheImpl implements IotModelCache {
fieldInfoCache.setAttributeType(item.getAttributeType());
fieldInfoCache.setHighspeed(item.getHighSpeed());
fieldInfoCache.setDatatype(item.getDataType());
fieldInfoCache.setLevel(item.getLevel());
fieldInfoCache.setStateDesc(item.getStateDesc());
iotFieldsMap.put(String.format("%d_%s", k, item.getAttributeCode()), fieldInfoCache);
});
});
@ -75,4 +79,42 @@ public class IotModelCacheImpl implements IotModelCache {
}
return fieldInfoCache.isCalculate();
}
@Override
public void refreshIotFieldCache(SysIotModelField sysIotModelField) {
IotFieldInfoCache fieldInfoCache = new IotFieldInfoCache();
fieldInfoCache.setAttributeCode(sysIotModelField.getAttributeCode());
fieldInfoCache.setPorder(sysIotModelField.getPorder());
fieldInfoCache.setAttributeName(sysIotModelField.getAttributeName());
fieldInfoCache.setAttributeType(sysIotModelField.getAttributeType());
fieldInfoCache.setHighspeed(sysIotModelField.getHighSpeed());
fieldInfoCache.setDatatype(sysIotModelField.getDataType());
fieldInfoCache.setLevel(sysIotModelField.getLevel());
fieldInfoCache.setStateDesc(sysIotModelField.getStateDesc());
iotFieldsMap.put(String.format("%d_%s", sysIotModelField.getIotModelId(), sysIotModelField.getAttributeCode()), fieldInfoCache);
}
@Override
public void removeIotFieldCache(Long modelId, String attributeCode){
iotFieldsMap.remove(String.format("%d_%s", modelId, attributeCode));
}
@Override
public void refreshIotModelInfoIdMap(SysIotModel sysIotModel){
IotModelInfoCache info = new IotModelInfoCache();
info.setIotModelId(sysIotModel.getId());
info.setIodModelCode(sysIotModel.getIotModelCode());
iotModelInfoIdMap.put(sysIotModel.getId(), info);
}
@Override
public void removeIotModelInfoIdMap(Long modelId) {
iotModelInfoIdMap.remove(modelId);
}
@Override
public IotFieldInfoCache getIotFiledCache(Long modelId, String attr) {
return iotFieldsMap.get(String.format("%d_%s", modelId, attr));
}
}

View File

@ -67,6 +67,9 @@ public class TDEngineService {
}
}
public HikariDataSource getHikariDataSource(){
return hikariDataSource;
}
/**
* 创建超级表
*/

View File

@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

View File

@ -0,0 +1,122 @@
package com.das.modules.data.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.das.modules.data.service.TDEngineService;
import com.das.modules.equipment.entity.SysEquipment;
import com.das.modules.equipment.mapper.SysEquipmentMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class ExportTdDataServiceImpl {
@Autowired
SysEquipmentMapper sysEquipmentMapper;
@Autowired
private TDEngineService tdEngineService;
@Value("${zipUrl}")
private String fileUrl;
public void exportDataCsvZip() throws IOException, SQLException {
StopWatch stopWatch = new StopWatch();
stopWatch.start("导出风机数据zip");
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -1);
String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
//获取所有风机数据
QueryWrapper<SysEquipment> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("object_type", 10002);
List<SysEquipment> sysEquipments = sysEquipmentMapper.selectList(queryWrapper);
//获取临时目录文件路径
String tempDir = String.valueOf(Files.createTempDirectory(null));
File zipFile = new File(fileUrl + "/data_"+yesterday+".zip");
List<File> fileList = new ArrayList<>();
try {
for (SysEquipment item : sysEquipments) {
String hTableName = "h" + item.getId();
String lTableName = "l" + item.getId();
File fileHighSpeed = new File(tempDir +"/" + "h_"+item.getCode()+"_"+yesterday + ".csv");
File fileLowSpeed = new File(tempDir +"/" + "l_"+item.getCode()+"_"+yesterday + ".csv");
getYesterdayData(hTableName, yesterday, fileHighSpeed.getPath());
getYesterdayData(lTableName, yesterday, fileLowSpeed.getPath());
fileList.add(fileLowSpeed);
fileList.add(fileHighSpeed);
}
//压缩文件
// 将文件添加到压缩文件中
ZipUtil.zip(zipFile, false, fileList.toArray(new File[0]));
stopWatch.stop();
log.debug(stopWatch.prettyPrint(TimeUnit.SECONDS));
}catch (Exception e){
log.error("导出风机数据zip失败{}",e);
}
finally {
if (!CollectionUtils.isEmpty(fileList)){
FileUtil.del(new File(fileList.get(0).getParent()));
}
}
}
public void getYesterdayData(String tableName, String time, String csvFilePath) {
// TDengine 查询语句
String query = "SELECT * FROM " + tableName + " WHERE updatetime >= '" + time + " 00:00:00' AND updatetime < '" + time + " 23:59:59.999'";
try (Connection conn = tdEngineService.getHikariDataSource().getConnection();
Statement smt = conn.createStatement();
ResultSet rs = smt.executeQuery(query)) {
writeResultSetToCsv(rs, csvFilePath);
}catch (Exception e){
log.error(tableName +"获取数据异常{}",e);
}
}
private void writeResultSetToCsv(ResultSet resultSet, String csvFilePath) throws IOException, SQLException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvFilePath))) {
// 写入列名
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
writer.write(metaData.getColumnName(i));
if (i < columnCount) writer.write(",");
}
writer.newLine();
// 写入数据
while (resultSet.next()) {
for (int i = 1; i <= columnCount; i++) {
String value = resultSet.getString(i);
writer.write(value == null ? "" : resultSet.getString(i));
if (i < columnCount) writer.write(",");
}
writer.newLine();
}
}catch (Exception e){
log.error("数据写入csv文件失败{}",e);
}
}
}

View File

@ -10,6 +10,7 @@ import com.das.common.config.SessionUtil;
import com.das.common.exceptions.ServiceException;
import com.das.common.utils.*;
import com.das.modules.auth.domain.vo.SysUserVo;
import com.das.modules.cache.service.CacheService;
import com.das.modules.data.service.impl.DataServiceImpl;
import com.das.modules.equipment.domain.dto.SysIotModelDto;
import com.das.modules.equipment.domain.dto.SysIotModelFieldDto;
@ -65,6 +66,9 @@ public class SysIotModelServiceImpl implements SysIotModelService {
@Autowired
SysRecordLogService sysRecordLogService;
@Autowired
CacheService cacheService;
public SysIotModelVo creatSysIotModel(SysIotModelDto sysIotModelDto) {
SysIotModel sysIotModel = new SysIotModel();
BeanCopyUtils.copy(sysIotModelDto, sysIotModel);
@ -81,7 +85,9 @@ public class SysIotModelServiceImpl implements SysIotModelService {
sysIotModel.setRevision(1);
sysIotModelMapper.insert(sysIotModel);
//刷新缓存
addModelCache(sysIotModel);
cacheService.getIotModelCache().refreshIotModelInfoIdMap(sysIotModel);
SysIotModelVo sysIotModelVo = new SysIotModelVo();
BeanCopyUtils.copy(sysIotModel, sysIotModelVo);
sysIotModelVo.setIotModelCode(sysIotModelDto.getIotModelCode());
@ -119,6 +125,8 @@ public class SysIotModelServiceImpl implements SysIotModelService {
throw new RuntimeException("该物模型下面有类型,不能删除");
}
sysIotModelMapper.deleteById(sysIotModelDto.getId());
//刷新缓存
cacheService.getIotModelCache().removeIotModelInfoIdMap(sysIotModelDto.getId());
deleteModelCache(sysIotModelDto.getId());
}
@ -184,6 +192,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
sysIotModelFieldMapper.insert(sysIotModelField);
//新增物模型属性缓存
cacheService.getIotModelCache().refreshIotFieldCache(sysIotModelField);
addModelFieldCache(sysIotModelField);
SysIotModelFieldVo sysIotModelFieldVo = new SysIotModelFieldVo();
BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo);
@ -216,6 +225,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
if (!oldSysIotField.getAttributeCode().equals(sysIotModelField.getAttributeCode()) || !oldSysIotField.getDataType().equals(sysIotModelField.getDataType()) || Objects.equals(oldSysIotField.getHighSpeed(), sysIotModelField.getHighSpeed())) {
//更新td表结构
updateTDStableOrColumn(sysIotModelField, oldSysIotField);
cacheService.getIotModelCache().refreshIotFieldCache(sysIotModelField);
updateModelFieldCache(sysIotModelField, oldSysIotField);
}
sysIotModelFieldMapper.updateById(sysIotModelField);
@ -232,6 +242,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
sysIotModelFieldMapper.deleteById(sysIotModelFieldDto.getId());
//删除物模型属性缓存
cacheService.getIotModelCache().removeIotFieldCache(sysIotModelField.getIotModelId(), sysIotModelField.getAttributeCode());
deleteModelFieldCache(sysIotModelField);
}
@ -488,6 +499,10 @@ public class SysIotModelServiceImpl implements SysIotModelService {
}
//新增pg数据库
sysIotModelFieldMapper.insertBatch(sysIotModelFieldList);
//刷新缓存
for (SysIotModelField item : sysIotModelFieldList){
cacheService.getIotModelCache().refreshIotFieldCache(item);
}
}
if (CollectionUtils.isNotEmpty(updateSysIotModelFieldList)) {
for (SysIotModelField item : updateSysIotModelFieldList) {
@ -496,6 +511,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
if (!oldSysIotField.getAttributeCode().equals(item.getAttributeCode()) && oldSysIotField.getDataType().equals(item.getDataType()) && Objects.equals(oldSysIotField.getHighSpeed(), item.getHighSpeed())) {
//更新td表结构
updateTDStableOrColumn(item, oldSysIotField);
cacheService.getIotModelCache().refreshIotFieldCache(item);
updateModelFieldCache(item, oldSysIotField);
}
}
@ -509,6 +525,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
for (SysIotModelField item : delSysIotModelFieldList) {
deleteTDStableOrColumn(item);
sysIotModelFieldMapper.deleteById(item);
cacheService.getIotModelCache().removeIotFieldCache(item.getIotModelId(), item.getAttributeCode());
deleteModelFieldCache(item);
}
}

View File

@ -1,17 +1,17 @@
package com.das.modules.node.command;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.das.common.exceptions.ServiceException;
import com.das.common.utils.AdminRedisTemplate;
import com.das.common.utils.StringUtils;
import com.das.modules.cache.domain.DeviceInfoCache;
import com.das.modules.cache.domain.IotFieldInfoCache;
import com.das.modules.cache.service.CacheService;
import com.das.modules.data.domain.DeviceEventInfo;
import com.das.modules.data.service.TDEngineService;
import com.das.modules.data.service.impl.DataServiceImpl;
import com.das.modules.node.constant.NodeConstant;
import com.das.modules.node.domain.bo.TerminalMessage;
import com.das.modules.node.domain.vo.DeviceEventVo;
import com.das.modules.node.service.NodeMessageService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -29,9 +29,6 @@ public class DeviceEventCommand implements BaseCommand{
@Autowired
AdminRedisTemplate adminRedisTemplate;
@Autowired
private DataServiceImpl dataService;
@Autowired
TDEngineService tdEngineService;
@ -72,18 +69,20 @@ public class DeviceEventCommand implements BaseCommand{
deviceEventInfo.setDeviceCode(deviceInfoCache.getDeviceCode());
deviceEventInfo.setFirstTriggeredCode(firstTriggeredCode);
String eventType = getEventType(item.getEventType());
String model = dataService.deviceModelMap.get(item.getDeviceId());
if (StringUtils.isEmpty(model)) {
Long iotModelId = deviceInfoCache.getIotModelId();
if (iotModelId == null) {
log.debug("未查询到物模型code设备id{}", item.getDeviceId());
}
String fieldName = dataService.fieldCodeNameMap.get(model).get(item.getAttrCode());
if (StringUtils.isEmpty(fieldName)) {
log.debug("未查询到物模型属性code设备id{}", item.getDeviceId());
IotFieldInfoCache iotFiledCache = cacheService.getIotModelCache().getIotFiledCache(iotModelId, item.getAttrCode());
if (iotFiledCache == null) {
log.debug("未查询到物模型属性设备id{},属性AttrCode{}", item.getDeviceId(),item.getAttrCode());
throw new ServiceException("未查询到物模型属性设备id"+item.getDeviceId()+",属性AttrCode"+item.getAttrCode());
}
String fieldName = iotFiledCache.getAttributeName();
deviceEventInfo.setEventType(item.getEventType());
deviceEventInfo.setConfirmed(0);
if (!StringUtils.isEmpty(eventType) && eventType.equals("遥信变位")) {
String stateDesc = dataService.stateDescMap.get(model).get(item.getAttrCode());
String stateDesc = iotFiledCache.getStateDesc();
if (item.getAttrValue().equals(0)) {
deviceEventInfo.setEventText(item.getAttrCode() + fieldName + " 复归");
if (StringUtils.isNotEmpty(stateDesc)) {
@ -97,7 +96,7 @@ public class DeviceEventCommand implements BaseCommand{
List<String> descList = Arrays.stream(stateDesc.split("\\|")).toList();
deviceEventInfo.setEventText(item.getAttrCode() + fieldName + descList.get(1));
}
Integer level = dataService.eventLevelMap.get(model).get(item.getAttrCode());
Integer level = iotFiledCache.getLevel();
log.debug("level:{}", level);
log.debug("fieldname{}", fieldName);
deviceEventInfo.setEventLevel(level == null ? 0 : level);

View File

@ -28,35 +28,18 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.jetbrains.annotations.NotNull;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.DefaultCategoryDataset;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@ -105,13 +88,9 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
List<Map<String, Object>> dataList = new ArrayList<>();
// 遍历数据填充Excel数据集
setTrendAnalyseExcelValue(mapsList, dataList);
//获取图表类别集
List<String> chartKey = getCharKey(map);
ExcelWriter writer = ExcelUtil.getWriter(RandomUtil.randomInt(100, 1000) + "statistics" + ".xlsx");
//设置Excel样式
setExcelStyle(writer, map, dataList);
//生成折线图
addChartToExcel(writer,dataList,StatisticalAnalysisConstant.TREND_ANALYSE,chartKey);
//下载Excel
downloadExcel(response, writer,StatisticalAnalysisConstant.TREND_ANALYSE);
}
@ -150,18 +129,9 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
setPowerCurveExcelValue(resultMap, dataList, curveItemEntitieList);
//获取功率曲线的列
LinkedHashMap<String, String> map = getPowerCurveColumnName(param);
//获取图表类别集
List<String> chartKey = getCharKey(map);
ExcelWriter writer = ExcelUtil.getWriter(RandomUtil.randomInt(100, 1000) + "statistics" + ".xlsx");
//设置Excel样式
setExcelStyle(writer, map, dataList);
//生成折线图
if (param.getDisplayCurve()==1){
addChartToExcel(writer,dataList,StatisticalAnalysisConstant.POWER_CURVE,chartKey);
}else {
//生成散点图
addScattersChartToExcel(writer,dataList,StatisticalAnalysisConstant.POWER_CURVE,chartKey);
}
//下载Excel
downloadExcel(response, writer,StatisticalAnalysisConstant.POWER_CURVE);
}
@ -191,15 +161,11 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
//自定义别名 别名的key和实体类中的名称要对应上
LinkedHashMap<String, String> map = gettrendContrastColumnName(param);
List<Map<String, Object>> dataList = new ArrayList<>();
//图表类别集
List<String> charKey = getCharKey(map);
// 遍历数据将数据添加到dataList中
setTrendContrastExcelValue(maps, dataList);
ExcelWriter writer = ExcelUtil.getWriter(RandomUtil.randomInt(100, 1000) + "statistics" + ".xlsx");
//设置Excel样式
setExcelStyle(writer, map, dataList);
//生成折线图
addChartToExcel(writer,dataList,StatisticalAnalysisConstant.TREND_CONTRAST,charKey);
//下载Excel
downloadExcel(response, writer,StatisticalAnalysisConstant.TREND_CONTRAST);
}
@ -284,22 +250,7 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
}
}
/**
* 获取图表类别集
* @param map Excel的列
* @return 图表类别集
*/
private List<String> getCharKey(LinkedHashMap<String, String> map) {
//获取图表类别集
List<String> chartKey = new ArrayList<>();
for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
String value = stringStringEntry.getValue();
if (!value.contains("时间")){
chartKey.add(value);
}
}
return chartKey;
}
/**
* 趋势对比填充Excel数据集
@ -542,75 +493,20 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
}
/**
* 使用JFreeChart生成折线图(图片),已弃用
* @param data excel数据集
* @param writer excel对象
* @param dataset 图表数据集
* @param titleStr 标题
* 获取图表类别集
* @param map Excel的列
* @return 图表类别集
*/
private void createChart(List<Map<String, Object>> data, ExcelWriter writer,
DefaultCategoryDataset dataset, String titleStr) {
// 获取Sheet对象
XSSFSheet xssfSheet = (XSSFSheet) writer.getSheet();
Workbook workbook = writer.getWorkbook();
JFreeChart chart = ChartFactory.createLineChart(
titleStr, // 图表标题
"", // 横轴标签
"", // 纵轴标签
dataset, // 数据集
PlotOrientation.VERTICAL, // 图表方向
true, // 是否显示图例
true, // 是否使用工具提示
false // 是否生成URL链接
);
// 设置图表标题的字体
TextTitle title = chart.getTitle();
title.setFont(new java.awt.Font("SimSun", java.awt.Font.BOLD, 16));
// 获取图表的绘图区域
CategoryPlot plot = chart.getCategoryPlot();
// 设置横轴标签
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setLabelFont(new java.awt.Font("SimSun", java.awt.Font.PLAIN, 12));
domainAxis.setMaximumCategoryLabelLines(1); // 可以控制标签行数
domainAxis.setCategoryMargin(3); // 控制类别之间的间距
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); // 旋转横轴标签为45度,90度为:UP_90
domainAxis.setLabelFont(new Font("SansSerif", Font.PLAIN, 7));//调整字体大小
// if (data.size() > 50) {
// domainAxis.setVisible(false); // 隐藏横坐标
// }
// 设置图例的字体
LegendTitle legend = chart.getLegend();
if (legend != null) {
legend.setItemFont(new java.awt.Font("SimSun", java.awt.Font.PLAIN, 12));
private List<String> getCharKey(LinkedHashMap<String, String> map) {
//获取图表类别集
List<String> chartKey = new ArrayList<>();
for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
String value = stringStringEntry.getValue();
if (!value.contains("时间")){
chartKey.add(value);
}
// 设置绘图区域的背景颜色
plot.setBackgroundPaint(Color.WHITE);
// 设置绘图区域的边框
plot.setOutlinePaint(Color.LIGHT_GRAY);
plot.setOutlineVisible(true);
// 设置网格线的颜色
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
// 设置线条的宽度
CategoryItemRenderer renderer1 = plot.getRenderer();
renderer1.setSeriesStroke(0, new BasicStroke(2.0f)); // 设置线条宽度
// 将图表保存为 PNG 文件
String chartFilePath = "lineChart.png";
// 调整图表尺寸
int width = 750;
int height = 400;
try {
ChartUtils.saveChartAsPNG(new File(chartFilePath), chart, width, height);
byte[] bytes = java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(chartFilePath));
int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
// 计算数据的最后一行,创建图表插入位置的锚点
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 1, 0, 1, 0, data.size() + 2, 15, data.size() + 30);
XSSFDrawing drawing = xssfSheet.createDrawingPatriarch();
drawing.createPicture(anchor, pictureIdx);
} catch (IOException e) {
throw new ServiceException("图表保存失败==" + e);
}
return chartKey;
}
/**

View File

@ -111,3 +111,5 @@ minio:
bucket: das
accessKey: das
secretKey: zaq12WSX
zipUrl: /log/zip/

View File

@ -114,3 +114,5 @@ minio:
publicBucket: das-dock
accessKey: das
secretKey: zaq12WSX
zipUrl: /log/zip/