This commit is contained in:
zhouhuang 2024-12-13 16:16:37 +08:00
commit 84cfc90b5d
16 changed files with 201 additions and 109 deletions

View File

@ -138,6 +138,9 @@ public class CalcService {
FunctionWindSpeedFactor windSpeedFactor = new FunctionWindSpeedFactor(dataService,cacheService); FunctionWindSpeedFactor windSpeedFactor = new FunctionWindSpeedFactor(dataService,cacheService);
aviator.addFunction(windSpeedFactor); aviator.addFunction(windSpeedFactor);
FunctionIsOnline isOnline = new FunctionIsOnline(adminRedisTemplate, cacheService);
aviator.addFunction(isOnline);
} }
/** /**

View File

@ -2,7 +2,6 @@ package com.das.modules.node.command;
import com.das.common.constant.EquipmentTypeIds; import com.das.common.constant.EquipmentTypeIds;
import com.das.common.utils.AdminRedisTemplate; 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.DeviceInfoCache;
import com.das.modules.cache.service.CacheService; import com.das.modules.cache.service.CacheService;
import com.das.modules.node.constant.NodeConstant; import com.das.modules.node.constant.NodeConstant;
@ -12,44 +11,57 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.text.MessageFormat;
@Slf4j @Slf4j
@Service(value = NodeConstant.HEARTBEAT) @Service(value = NodeConstant.HEARTBEAT)
public class HeartbeatCommand implements BaseCommand{ public class HeartbeatCommand implements BaseCommand{
public static final long HEARTBEAT_TTL = 60L; public static final long HEARTBEAT_TTL = 12L;
@Autowired @Autowired
AdminRedisTemplate adminRedisTemplate; AdminRedisTemplate adminRedisTemplate;
@Autowired @Autowired
CacheService cacheService; CacheService cacheService;
/**
* 执行命令方法
* 该方法处理接收到的终端消息特别是心跳报文中的设备和链路在线状态更新
*
* @param data 包含心跳报文信息的TerminalMessage对象
*/
@Override @Override
public void doCommand(TerminalMessage data) { public void doCommand(TerminalMessage data) {
log.info("收到[heartbeat]报文");
// 解析心跳报文中的数据信息
JsonNode dataInfo = data.getData(); JsonNode dataInfo = data.getData();
if (!dataInfo.isEmpty()) { if (!dataInfo.isEmpty()) {
// 处理链路信息
JsonNode links = data.getData().get("links"); JsonNode links = data.getData().get("links");
if (links != null && links.isArray()) { if (links != null && links.isArray()) {
for (JsonNode linkNode : links) { for (JsonNode linkNode : links) {
String linkId = linkNode.get("linkId").asText(); String linkId = linkNode.get("linkId").asText();
boolean online = linkNode.get("online").asBoolean(); boolean online = linkNode.get("online").asBoolean();
String key = String.format("link:%d:online", linkId, online); String key = String.format("link:%s:online", linkId);
// 更新链路在线状态到Redis
adminRedisTemplate.set(key, online ? 1 : 0); adminRedisTemplate.set(key, online ? 1 : 0);
adminRedisTemplate.expire(key, HEARTBEAT_TTL); adminRedisTemplate.expire(key, HEARTBEAT_TTL);
} }
} }
// 处理设备信息
JsonNode devices = data.getData().get("devices"); JsonNode devices = data.getData().get("devices");
if (devices != null && devices.isArray()) { if (devices != null && devices.isArray()) {
for (JsonNode device : devices) { for (JsonNode device : devices) {
long deviceId = device.get("deviceId").asLong(); long deviceId = device.get("deviceId").asLong();
boolean online = device.get("online").asBoolean(); boolean online = device.get("online").asBoolean();
// 获取设备缓存信息
DeviceInfoCache deviceInfoCacheById = cacheService.getEquipmentCache().getDeviceInfoCacheById(deviceId); DeviceInfoCache deviceInfoCacheById = cacheService.getEquipmentCache().getDeviceInfoCacheById(deviceId);
if (deviceInfoCacheById == null || !deviceInfoCacheById.getObjectType().equals(EquipmentTypeIds.EQUIPMENT_TYPE_STATION_WTG)) { if (deviceInfoCacheById == null || !deviceInfoCacheById.getObjectType().equals(EquipmentTypeIds.EQUIPMENT_TYPE_STATION_WTG)) {
continue; continue;
} }
//判断是不是风机 // 判断是不是风机
String keyDeviceOnline = String.format("device:%d:online", deviceId); String keyDeviceOnline = String.format("device:%d:online", deviceId);
// 更新设备在线状态到Redis
adminRedisTemplate.set(keyDeviceOnline, online ? 1 : 0); adminRedisTemplate.set(keyDeviceOnline, online ? 1 : 0);
adminRedisTemplate.expire(keyDeviceOnline, HEARTBEAT_TTL); adminRedisTemplate.expire(keyDeviceOnline, HEARTBEAT_TTL);
@ -57,6 +69,7 @@ public class HeartbeatCommand implements BaseCommand{
String keyCommFaultState = String.format("RT:%d:commfaultstate",deviceId); String keyCommFaultState = String.format("RT:%d:commfaultstate",deviceId);
Integer plcDeviceStatus = adminRedisTemplate.get(keyPLCDeviceStatus); Integer plcDeviceStatus = adminRedisTemplate.get(keyPLCDeviceStatus);
log.debug("设备ID:{},在线状态:{},通讯状态: {}", deviceId, online, plcDeviceStatus); log.debug("设备ID:{},在线状态:{},通讯状态: {}", deviceId, online, plcDeviceStatus);
// 根据设备在线状态和通讯状态更新通讯故障状态
if (plcDeviceStatus == null){ if (plcDeviceStatus == null){
adminRedisTemplate.set(keyCommFaultState, online ? 0 : 1); adminRedisTemplate.set(keyCommFaultState, online ? 0 : 1);
} }

View File

@ -238,7 +238,7 @@ public class NodeMessageServiceImpl extends TextWebSocketHandler implements Node
@Override @Override
public void handleData(TerminalMessage data) { public void handleData(TerminalMessage data) {
JsonNode jsonNode = data.getData(); JsonNode jsonNode = data.getData();
log.info("收到消息:{}",data.getData()); log.debug("收到消息:{}",data.getData());
String deviceId = jsonNode.get("deviceId").asText(); String deviceId = jsonNode.get("deviceId").asText();
JsonNode values = jsonNode.get("values"); JsonNode values = jsonNode.get("values");
JsonNode archiveValues = jsonNode.get("archiveValues"); JsonNode archiveValues = jsonNode.get("archiveValues");
@ -258,7 +258,6 @@ public class NodeMessageServiceImpl extends TextWebSocketHandler implements Node
String key = String.format("RT:%s:%s", deviceId, fieldName.toLowerCase()); String key = String.format("RT:%s:%s", deviceId, fieldName.toLowerCase());
keyValueMap.put(key, values.get(fieldName)); keyValueMap.put(key, values.get(fieldName));
} }
log.info("values解析成功");
} }
if (archiveValues != null){ if (archiveValues != null){
@ -274,7 +273,6 @@ public class NodeMessageServiceImpl extends TextWebSocketHandler implements Node
lowSpeedValueMap.put(fieldName, archiveValues.get(fieldName)); lowSpeedValueMap.put(fieldName, archiveValues.get(fieldName));
} }
} }
log.info("archive解析成功");
} }
//更新td //更新td
if (!highSpeedValueMap.isEmpty()) { if (!highSpeedValueMap.isEmpty()) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@ -462,8 +462,62 @@ systemctl enable das
```shell ```shell
mkdir -p /das/app mkdir -p /das/app
cd /das/app cd /das/app
wget https://oss.jsspisoft.com/ wget https://oss.jsspisoft.com/public/software/das/das-dn.tar.gz
tar zxvf das-dn.tar.gz
rm -f das-dn.tar.gz
``` ```
### 程序配置
编辑文件`/das/app/das-dn/envfile`
```toml
#das服务地址
ISS_WS_HOST=127.0.0.1
#das服务端口
ISS_WS_PORT=8080
#节点ID
ISS_WS_NODEID=1
```
### 配置服务
创建服务文件`/etc/systemd/system/das-dn.service`,内容如下:
```toml
[Unit]
Description=DAS DN Service
After=network.target
[Service]
Type=simple
EnvironmentFile=/das/app/das-dn/envfile
ExecStart=/das/app/das-dn/bin/application -d ./rtufiles -h $ISS_WS_HOST -p $ISS_WS_PORT -n $ISS_WS_NODEID
Restart=always
RestartSec=10
StartLimitInterval=0
WorkingDirectory=/das/app/das-dn
[Install]
WantedBy=multi-user.target
```
### 服务启动
```bash
systemctl start das-dn
systemctl enable das-dn
```
## 前端UI部署
前端只需要部署静态文件就行了
```shell
mkdir -p /das/app
wget https://oss.jsspisoft.com/public/software/das/ui.tar.gz
tar zxvf ui.tar.gz
rm -f ui.tar.gz
```
这样就部署好了。

View File

@ -987,6 +987,8 @@ const realTimeDataState = computed(() => {
return '停机' return '停机'
case 11: case 11:
return '待机' return '待机'
case 33:
return '通讯中断'
case 1110: case 1110:
return '解缆状态' return '解缆状态'
case 1111: case 1111:

View File

@ -341,23 +341,6 @@ const currentDayStatus = ref({
}) })
const deviceCode = ref([]) const deviceCode = ref([])
const FanList = ref([]) const FanList = ref([])
const getRealTimeState = (data: any) => {
if (data.iturbineoperationmode) {
if (data.iturbineoperationmode > 1 && data.iturbineoperationmode < 6) {
return 2
}
if (data.iturbineoperationmode === 21) {
return 20
}
return data.iturbineoperationmode
} else if (data.iyplevel === 10) {
return 1110
} else if (data.gridlostdetected === 1) {
return 1111
} else if (data.ibplevel === 200) {
return 1112
}
}
const StatusListData = () => { const StatusListData = () => {
getWindTurbineMatrixData().then((res) => { getWindTurbineMatrixData().then((res) => {
if (res.code == 200) { if (res.code == 200) {

View File

@ -15,41 +15,44 @@
:width="item.width" :width="item.width"
> >
<template #default="scope"> <template #default="scope">
<div v-if="item.prop === 'iturbineoperationmode'"> <div v-if="item.prop === 'processedoperationmode'">
<el-tag v-if="scope.row.locked === 1" color="rgba(254,55,49,0.20)" style="color: #fe3731">已锁定</el-tag> <el-tag v-if="scope.row.locked === 1" color="rgba(254,55,49,0.20)" style="color: #fe3731">已锁定</el-tag>
<el-tag v-if="scope.row.iturbineoperationmode === 20" color="rgba(0,100,170,0.20)" style="color: #0064aa" <el-tag v-if="scope.row.processedoperationmode === 20" color="rgba(0,100,170,0.20)" style="color: #0064aa"
>并网</el-tag >并网</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 10" color="rgba(0,160,150,0.20)" style="color: #00a096" <el-tag v-if="scope.row.processedoperationmode === 10" color="rgba(0,160,150,0.20)" style="color: #00a096"
>维护</el-tag >维护</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 8" color="rgba(255,126,0,0.20)" style="color: #ff7e00" <el-tag v-if="scope.row.processedoperationmode === 8" color="rgba(255,126,0,0.20)" style="color: #ff7e00"
>限功率运行</el-tag >限功率运行</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 0" color="rgba(153,153,153,0.20)" style="color: #666666" <el-tag v-if="scope.row.processedoperationmode === 0" color="rgba(153,153,153,0.20)" style="color: #666666"
>离线</el-tag >离线</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 16" color="rgba(6,180,41,0.20)" style="color: #06b429" <el-tag v-if="scope.row.processedoperationmode === 16" color="rgba(6,180,41,0.20)" style="color: #06b429"
>启动</el-tag >启动</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 6" color="rgba(254,55,49,0.20)" style="color: #fe3731" <el-tag v-if="scope.row.processedoperationmode === 6" color="rgba(254,55,49,0.20)" style="color: #fe3731"
>正常停机</el-tag >正常停机</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 1" color="rgba(254,55,49,0.20)" style="color: #fe3731" <el-tag v-if="scope.row.processedoperationmode === 1" color="rgba(254,55,49,0.20)" style="color: #fe3731"
>外部因素导致停机</el-tag >外部因素导致停机</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 2" color="rgba(254,55,49,0.20)" style="color: #fe3731" <el-tag v-if="scope.row.processedoperationmode === 2" color="rgba(254,55,49,0.20)" style="color: #fe3731"
>停机</el-tag >停机</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 11" color="rgba(255,182,0,0.20)" style="color: #ffb600" <el-tag v-if="scope.row.processedoperationmode === 11" color="rgba(255,182,0,0.20)" style="color: #ffb600"
>待机</el-tag >待机</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 1110" color="rgba(153,153,153,0.20)" style="color: #666666" <el-tag v-if="scope.row.processedoperationmode === 1110" color="rgba(153,153,153,0.20)" style="color: #666666"
>解缆状态</el-tag >解缆状态</el-tag
> >
<el-tag v-if="scope.row.iturbineoperationmode === 1111" color="rgba(254,55,49,0.20)" style="color: #fe3731" <el-tag v-if="scope.row.processedoperationmode === 1111" color="rgba(254,55,49,0.20)" style="color: #fe3731"
>电网故障停机</el-tag >电网故障停机</el-tag
> >
<el-tag v-if="scope.row.processedoperationmode === 33" color="rgba(153, 153, 153, 0.2)" style="color: #999999"
>通讯中断</el-tag
>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@ -174,7 +177,7 @@
</div> </div>
<div class="right"> <div class="right">
<div class="num">33</div> <div class="num">33</div>
<div class="unit">MW</div> <div class="unit">MVar</div>
</div> </div>
</div> </div>
<div class="rect"> <div class="rect">
@ -184,7 +187,7 @@
</div> </div>
<div class="right"> <div class="right">
<div class="num">6</div> <div class="num">6</div>
<div class="unit">MW</div> <div class="unit">MVar</div>
</div> </div>
</div> </div>
<div class="check"> <div class="check">
@ -227,17 +230,17 @@
</div> </div>
</div> </div>
<div class="check"> <div class="check">
<div class="left">AVC可增</div> <div class="left">AVC可增</div>
<div class="right"> <div class="right">
<div class="num">5</div> <div class="num">5</div>
<div class="unit">MW</div> <div class="unit">MVar</div>
</div> </div>
</div> </div>
<div class="check"> <div class="check">
<div class="left">AVC可减</div> <div class="left">AVC可减</div>
<div class="right"> <div class="right">
<div class="num">5</div> <div class="num">5</div>
<div class="unit">MW</div> <div class="unit">MVar</div>
</div> </div>
</div> </div>
</div> </div>
@ -331,7 +334,7 @@ const tableColumn = [
}, },
{ {
label: '状态', label: '状态',
prop: 'iturbineoperationmode', prop: 'processedoperationmode',
width: '', width: '',
}, },
] ]
@ -354,7 +357,7 @@ const createTableReqParams = (airblowerList: { irn: string; name: string }[]) =>
airBlowerIds.push(item.irn) airBlowerIds.push(item.irn)
return { return {
deviceId: item.irn, deviceId: item.irn,
attributes: [...curTableKey, 'iturbineoperationmode', 'iyplevel', 'gridlostdetected', 'ibplevel'], attributes: [...curTableKey, 'processedoperationmode', 'iyplevel', 'gridlostdetected', 'ibplevel'],
} }
}) })
return { params, airBlowerInfo, airBlowerIds } return { params, airBlowerInfo, airBlowerIds }
@ -393,7 +396,7 @@ const getAirBlowerList = () => {
belongLine: airBlowerInfoObj[id].belongLine, belongLine: airBlowerInfoObj[id].belongLine,
deviceCode: airBlowerInfoObj[id].deviceCode, deviceCode: airBlowerInfoObj[id].deviceCode,
...realData, ...realData,
iturbineoperationmode: state, processedoperationmode: state,
} }
}) })
tableData.value = data tableData.value = data

View File

@ -122,6 +122,9 @@
<el-tag v-if="scope.row.processedoperationmode === 1111" color="rgba(254,55,49,0.20)" style="color: #fe3731" <el-tag v-if="scope.row.processedoperationmode === 1111" color="rgba(254,55,49,0.20)" style="color: #fe3731"
>电网故障停机</el-tag >电网故障停机</el-tag
> >
<el-tag v-if="scope.row.processedoperationmode === 33" color="rgba(153, 153, 153, 0.2)" style="color: #999999"
>通讯中断</el-tag
>
</div> </div>
<div v-if="item.prop === 'chart'" @click="openLineChart(scope.row)" class="operate"> <div v-if="item.prop === 'chart'" @click="openLineChart(scope.row)" class="operate">
<div class="chartIcon"> <div class="chartIcon">
@ -272,6 +275,10 @@ const airBlowerSelectOptions = reactive<{ [K in SelectTypeKeyUnionType]: { label
label: '停机', label: '停机',
value: 2, value: 2,
}, },
{
label: '通讯中断',
value: 33,
},
{ {
label: '解缆状态', label: '解缆状态',
value: 1110, value: 1110,

View File

@ -6,32 +6,35 @@
@click="handleClick(item)" @click="handleClick(item)"
@contextmenu.prevent="windContextMenu($event,item)" @contextmenu.prevent="windContextMenu($event,item)"
> >
<div class="FanList-panel" :class="item.standard == true ? 'wind-mark' : 'wind-default'"> <div class="FanList-panel" :class="{
'wind-mark': item.standard==1,
'wind-default': item.standard==0,
'wind-offline': item.attributeMap.processedoperationmode == 33
}">
<div class="fanlist-top"> <div class="fanlist-top">
<span :class="item.standard == true ? 'wind-mark-icon' : 'fanlist-icon'"> <span :class="item.standard == 1 ? 'wind-mark-icon' : 'fanlist-icon'">
<img :class="item.standard == true ? '' : 'wind-picture'" src="~assets/dashboard/biaogan.png" alt="" /> <img :class="item.standard == 1 ? '' : 'wind-picture'" src="~assets/dashboard/biaogan.png" alt="" />
</span> </span>
<span class="fanlist-name"> {{ item.name }}</span> <span class="fanlist-name"> {{ item.name }}</span>
<el-tag v-if="item.attributeMap.processedoperationmode === 20" class="tag-panel is-primary" type="primary">并网</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 20" class="tag-panel is-primary" type="primary">并网</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 11" class="tag-panel is-warning" type="primary">待机</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 11" class="tag-panel is-warning" type="primary">待机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 16" class="tag-panel is-success" type="primary">启动</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 16" class="tag-panel is-success" type="primary">启动</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 10" class="tag-panel is-maintenance" type="primary" <el-tag v-if="item.attributeMap.processedoperationmode === 10" class="tag-panel is-maintenance" type="primary"
>维护</el-tag >维护</el-tag>
>
<el-tag v-if="item.attributeMap.processedoperationmode === 0" class="tag-panel is-offline" type="primary">离线</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 0" class="tag-panel is-offline" type="primary">离线</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 8" class="tag-panel info" type="primary">限功率运行</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 8" class="tag-panel info" type="primary">限功率运行</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 6" class="tag-panel is-danger" type="primary">正常停机</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 6" class="tag-panel is-danger" type="primary">正常停机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 1" class="tag-panel is-danger" type="primary" <el-tag v-if="item.attributeMap.processedoperationmode === 1" class="tag-panel is-danger" type="primary"
>外部因素导致停机</el-tag >外部因素导致停机</el-tag>
>
<el-tag v-if="item.attributeMap.processedoperationmode === 2" class="tag-panel is-danger" type="primary">停机</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 2" class="tag-panel is-danger" type="primary">停机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 1110" class="tag-panel is-info" type="primary">解缆状态</el-tag> <el-tag v-if="item.attributeMap.processedoperationmode === 1110" class="tag-panel is-info" type="primary">解缆状态</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 1111" class="tag-panel is-danger" type="primary" <el-tag v-if="item.attributeMap.processedoperationmode === 1111" class="tag-panel is-danger" type="primary"
>电网故障停机</el-tag >电网故障停机</el-tag>
>
<el-tag v-if="item.attributeMap.processedoperationmode === 1112" class="tag-panel is-danger" type="primary" <el-tag v-if="item.attributeMap.processedoperationmode === 1112" class="tag-panel is-danger" type="primary"
>安全链停机</el-tag >安全链停机</el-tag>
> <el-tag v-if="item.attributeMap.processedoperationmode === 33" class="tag-panel is-offline" type="primary"
>通讯中断</el-tag>
</div> </div>
<div class="fanlist-main"> <div class="fanlist-main">
<el-row> <el-row>
@ -254,6 +257,10 @@ const sendManualCommand = (type: 1 | 0) => {
background-image: linear-gradient(180deg, #f0f6ff 0%, #ffffff 50%); background-image: linear-gradient(180deg, #f0f6ff 0%, #ffffff 50%);
border: 1px solid #e1edf6; border: 1px solid #e1edf6;
} }
.wind-offline {
background-image: linear-gradient(180deg, #dddddd 0%, #ffffff 93%);
border: 1px solid #eeeeee;
}
.wind-picture { .wind-picture {
display: none; display: none;
} }

View File

@ -46,12 +46,7 @@
<el-table-column prop="status" :label="LinkMonitorFieldsEnums['status']" align="center" width="80"> <el-table-column prop="status" :label="LinkMonitorFieldsEnums['status']" align="center" width="80">
<template #default="scope"> <template #default="scope">
<div class="status-container"> <div class="status-container">
<span <span :class="scope.row.status == 0 ? 'status-dot-online' : 'status-dot-offline'"></span>
:class="{
'status-dot-online': !scope.row.status,
'status-dot-offline': scope.row.status,
}"
></span>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@ -102,13 +97,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, nextTick } from 'vue' import { reactive, ref, nextTick, onUnmounted } from 'vue'
import { ElContainer, ElAside, ElHeader, ElMain, ElTree, ElInput, ElMessage, ElButton, ElTable, TreeInstance } from 'element-plus' import { ElContainer, ElAside, ElHeader, ElMain, ElTree, ElInput, ElMessage, ElButton, ElTable, TreeInstance } from 'element-plus'
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import { LinkMonitorFieldsEnums, LinkMonitorTreeType, LinkMonitorTableType } from './type' import { LinkMonitorFieldsEnums, LinkMonitorTreeType, LinkMonitorTableType } from './type'
import { getNodeListReq, getLinkListReq } from '/@/api/backend/linkMonitor/request' import { getNodeListReq, getLinkListReq } from '/@/api/backend/linkMonitor/request'
import { debounce, cloneDeep } from 'lodash' import { debounce, cloneDeep } from 'lodash'
import { protocolList } from '/@/views/backend/node/utils'
const LinkTreePropReplace = { const LinkTreePropReplace = {
label: 'nodeName', label: 'nodeName',
children: 'children', children: 'children',
@ -184,7 +179,8 @@ const getlinkTreeList = () => {
getlinkTreeList().then((res) => { getlinkTreeList().then((res) => {
curContextMenuTreeData.value = cloneDeep(res as LinkMonitorTreeType) curContextMenuTreeData.value = cloneDeep(res as LinkMonitorTreeType)
linkTreeRef.value?.setCurrentKey(curContextMenuTreeData.value!.id!) linkTreeRef.value?.setCurrentKey(curContextMenuTreeData.value!.id!)
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value) createTimer()
// getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
}) })
const searchLinkTree = () => { const searchLinkTree = () => {
@ -249,7 +245,8 @@ const linkTreeNodeCollapse = (node: any) => {
} }
const linkTreeNodeClick = (target: LinkMonitorTreeType) => { const linkTreeNodeClick = (target: LinkMonitorTreeType) => {
curContextMenuTreeData.value = cloneDeep(target) curContextMenuTreeData.value = cloneDeep(target)
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value) createTimer()
// getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
} }
const renderContent = (h: any, { node, data }: any) => { const renderContent = (h: any, { node, data }: any) => {
const label = node.label || '' const label = node.label || ''
@ -266,10 +263,12 @@ const renderContent = (h: any, { node, data }: any) => {
const linkMonitorInputValue = ref('') const linkMonitorInputValue = ref('')
const searchLinkMonitor = () => { const searchLinkMonitor = () => {
if (linkMonitorInputValue.value === '') { if (linkMonitorInputValue.value === '') {
getlinkMonitorList(curContextMenuTreeData.value!.id!) // getlinkMonitorList(curContextMenuTreeData.value!.id!)
createTimer()
return return
} }
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value) createTimer()
// getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
} }
const linkMonitorTableData = ref<LinkMonitorTableType[]>([]) const linkMonitorTableData = ref<LinkMonitorTableType[]>([])
@ -282,17 +281,23 @@ const paginationOptions = reactive({
pageSizes: [20, 50, 100], pageSizes: [20, 50, 100],
}) })
const getcurrentPage = () => { const getcurrentPage = () => {
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value) // getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
createTimer()
} }
const protocolList = [
{ label: 'IEC104主 *', value: 8 }, // const protocolList = [
{ label: 'IEC104从 *', value: 9 }, // // *
{ label: 'MODBUSRTU主 *', value: 12 }, // { label: 'IEC104 *', value: 9 },
{ label: 'MODBUSTCP主 *', value: 16 }, // { label: 'MODBUSTCP *', value: 17 },
] // { label: 'MODBUS', value: 80 },
// { label: 'ADS', value: 81 },
// ]
const getlinkMonitorList = (nodeId: string, linkName?: string) => { const getlinkMonitorList = (nodeId: string, linkName?: string) => {
getLinkListReq({ nodeId, linkName, pageNum: paginationOptions.current, pageSize: paginationOptions.pageSize }) getLinkListReq({ nodeId, linkName, pageNum: paginationOptions.current, pageSize: paginationOptions.pageSize, withStatus: 1 })
.then((res) => { .then((res) => {
if (!res.rows.length) {
clearTimer()
}
if (res.rows) { if (res.rows) {
linkMonitorTableData.value = res.rows.map((item) => { linkMonitorTableData.value = res.rows.map((item) => {
return { return {
@ -303,10 +308,12 @@ const getlinkMonitorList = (nodeId: string, linkName?: string) => {
paginationOptions.total = res.total paginationOptions.total = res.total
} else { } else {
ElMessage.error(res.msg ?? '查询失败') ElMessage.error(res.msg ?? '查询失败')
clearTimer()
} }
}) })
.catch((err) => { .catch((err) => {
ElMessage.error(err?.response?.data?.msg ?? '查询失败') ElMessage.error(err?.response?.data?.msg ?? '查询失败')
clearTimer()
}) })
} }
@ -323,6 +330,22 @@ const startLink = (val: LinkMonitorTableType) => {
const stopLink = (val: LinkMonitorTableType) => { const stopLink = (val: LinkMonitorTableType) => {
console.log('stopLink') console.log('stopLink')
} }
let timer: any = null
const createTimer = () => {
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
timer && clearInterval(timer)
timer = null
timer = setInterval(() => {
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
}, 5000)
}
const clearTimer = () => {
timer && clearInterval(timer)
timer = null
}
onUnmounted(() => {
clearTimer()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -35,6 +35,7 @@ export type GetLinkMonitorTableParam = {
linkName?: string linkName?: string
pageNum: number pageNum: number
pageSize: number pageSize: number
withStatus?: number
} }
export enum LinkMonitorFieldsEnums { export enum LinkMonitorFieldsEnums {

View File

@ -178,6 +178,7 @@ import {
uploadNodeReq, uploadNodeReq,
submitNodeConfigReq, submitNodeConfigReq,
} from '/@/api/backend/node/request' } from '/@/api/backend/node/request'
import {protocolList} from '/@/views/backend/node/utils'
import { getInstitutionalTreeListReq } from '/@/api/backend/org/request' import { getInstitutionalTreeListReq } from '/@/api/backend/org/request'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import ProtocolComponent from './protocol.vue' import ProtocolComponent from './protocol.vue'
@ -530,14 +531,6 @@ const getLinkData = (nodeId: string, linkName?: string) => {
}) })
} }
const protocolList = [
// *
{ label: 'IEC104从 *', value: 9 },
{ label: 'MODBUSTCP从 *', value: 17 },
{ label: 'MODBUS', value: 80 },
{ label: 'ADS', value: 81 },
{ label: '故障日志', value: 79 },
]
const protocolPartVisible = ref(false) const protocolPartVisible = ref(false)
const protocolDisabled = ref(false) const protocolDisabled = ref(false)

View File

@ -1052,6 +1052,22 @@ const formColumnList: formColumnType[] = [
value: true, value: true,
}, },
}, },
{
key: 'adsUser',
data: {
label: 'ADS账号',
type: 'input',
value: '',
},
},
{
key: 'adsPassword',
data: {
label: 'ADS密码',
type: 'password',
value: '',
},
},
{ {
key: 'ftpMode', key: 'ftpMode',
data: { data: {
@ -1101,26 +1117,6 @@ const formColumnList: formColumnType[] = [
showValue: '1', showValue: '1',
}, },
}, },
{
key: 'adsUser',
data: {
label: 'ADS账号',
type: 'input',
value: '',
showKey: 'ftpMode',
showValue: '1',
},
},
{
key: 'adsPassword',
data: {
label: 'ADS密码',
type: 'password',
value: '',
showKey: 'ftpMode',
showValue: '1',
},
},
], ],
timeOutOption: [], timeOutOption: [],
otherOption: [], otherOption: [],

View File

@ -1,5 +1,14 @@
import { LocaleType, BooleanNumber, SheetTypes } from '@univerjs/core' import { LocaleType, BooleanNumber, SheetTypes } from '@univerjs/core'
export const protocolList = [
// * 代表需要配置的协议
{ label: 'IEC104从 *', value: 9 },
{ label: 'MODBUSTCP从 *', value: 17 },
{ label: 'MODBUS', value: 80 },
{ label: 'ADS', value: 81 },
{ label: '故障日志', value: 79 },
]
export const excelDefaultConfig: any = { export const excelDefaultConfig: any = {
// IEC104从 // IEC104从
9: { 9: {

View File

@ -414,7 +414,7 @@ const statAnalysisExport = () => {
const calculateAverages = (data: any) => { const calculateAverages = (data: any) => {
let maxWindSpeed = Math.max(...data.map((item: any) => item[0])) let maxWindSpeed = Math.max(...data.map((item: any) => item[0]))
let interval = 5 // 5m/s let interval = 0.5
let result = [] let result = []
for (let windSpeed = 0; windSpeed <= maxWindSpeed; windSpeed += interval) { for (let windSpeed = 0; windSpeed <= maxWindSpeed; windSpeed += interval) {