You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
451 lines
17 KiB
451 lines
17 KiB
import React, { useEffect, useState, useRef, useMemo } from 'react'
|
|
import { connect } from 'react-redux'
|
|
import { Spin, Card, CardGroup, Form, Select, Input, Button, Table, Pagination, Tooltip,Modal,Switch } from 'antd'
|
|
import ExportData from '../components/export-data'
|
|
import moment from 'moment'
|
|
|
|
const Network = props => {
|
|
const { dispatch, actions, user, clientHeight, thingId, deviceListAlarms, devicesCardStatusList, project, token,thingStatus } = props
|
|
const { analysis } = actions
|
|
// const form = useRef() //表单
|
|
const [form] = Form.useForm();
|
|
const [deployData, setDeployData] = useState([])
|
|
const [deviceData, setDeviceData] = useState([])
|
|
const [deviceMetasDeployed, setDeviceMetasDeployed] = useState([])
|
|
const [sensorId, setSensorId] = useState([])
|
|
const [sensorsDataItems, setSensorsDataItems] = useState({})
|
|
const [tableData, setTableData] = useState([]) //最新一次的数据
|
|
const [lastData, setLastData] = useState([]) //最终数据
|
|
const [lastDataCopy, setLastDataCopy] = useState([]) //最终数据
|
|
const [searchType, setSearchType] = useState('')
|
|
const [searchName, setSearchName] = useState('')
|
|
const [typeList, setTypeList] = useState([])
|
|
const [deviceId,setDeviceId] = useState([])
|
|
const [modalVis,setModalVis]=useState(false)
|
|
const [loading,setLoading]=useState(true)
|
|
const [status,setStatus]=useState(false)//空开设备开关状态
|
|
const [controlId,setControlId]=useState('')
|
|
const [id,setId]=useState('')//设计设备的id
|
|
const [param,setParam]=useState('')//开与关
|
|
const [text,setText]=useState('')
|
|
const DeviceTypes = {
|
|
'DTU': 'DTU',
|
|
'gateway': '网关',
|
|
'sensor': '传感器',
|
|
'acqUnit': '采集单元',
|
|
'dau.gateway': '分布式智能云采集网关',
|
|
'dau.node': '分布式智能云采集节点',
|
|
'tcp.dtu': '工作站',
|
|
}
|
|
|
|
useEffect(() => {
|
|
setLastData([])
|
|
setLastDataCopy([])
|
|
}, [project])
|
|
|
|
useEffect(() => {
|
|
if (thingId) {
|
|
let dataList = []
|
|
dispatch(analysis.getThingsDeploy(thingId, token)).then(rs => {
|
|
if (rs.success) {
|
|
setDeployData(rs.payload.data)
|
|
dataList = rs.payload.data
|
|
//列表渲染数据
|
|
let da = []
|
|
if (dataList.instances) {
|
|
Object.keys(dataList.instances).forEach(i => {
|
|
if (dataList.instances[i].type == 's.d') {
|
|
da.push({
|
|
sensorId: i,
|
|
sensorName: dataList.instances[i]?.name,
|
|
deviceType: dataList?.instances[i]?.instance?.properties?.deviceType,
|
|
model:dataList?.instances[i]?.instance?.properties?.productType,
|
|
collectTime: '--',
|
|
data: '--',
|
|
iotCardStatus: '--',
|
|
status: '--',
|
|
option: '--',
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
dispatch(analysis.findDeviceMetaDeployed(thingId, token)).then(res => {
|
|
if (res.success) {
|
|
setDeviceMetasDeployed(res.payload.data)
|
|
const deviceMetaDeployed = res.payload.data
|
|
if (deviceMetaDeployed && dataList && deviceMetaDeployed.devices) {
|
|
const sensorsId = []
|
|
let deviceIds = [] //所有设备的id
|
|
|
|
const sensorsDataItems = {}
|
|
for (const id in dataList.instances) {
|
|
let searchId=''//查询e9c设备状态的id
|
|
let controlId=''//控制e9c设备开关的id
|
|
deviceIds.push(id)
|
|
const instances = dataList.instances[id]
|
|
if (instances.type == 's.d' && instances.instance.properties.deviceType == 'sensor') {
|
|
if(instances.instance.properties.model == 'E9C'){
|
|
for(const key in instances?.instance?.interfaces){
|
|
Object.keys(instances?.instance?.interfaces[key]?.capabilities).forEach(
|
|
(kk,index)=>{
|
|
if(index===0){
|
|
searchId=instances?.instance?.interfaces[key]?.capabilities[kk]?.dimension?.id
|
|
}
|
|
if(index===1){
|
|
controlId=instances?.instance?.interfaces[key]?.capabilities[kk]?.dimension?.id
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
const meta = deviceMetaDeployed.devices.find(m => m.id == instances.instance.deviceMetaId)
|
|
sensorsDataItems[id] = {
|
|
items: {},
|
|
deviceName: instances.name,
|
|
model:instances.instance.properties.productType,
|
|
searchId:instances.instance.properties.model == 'E9C'?searchId:null,
|
|
controlId:instances.instance.properties.model == 'E9C'?controlId:null,
|
|
}
|
|
if (meta) {
|
|
sensorsDataItems[id].items = meta.capabilities[0].properties.reduce((p, n) => {
|
|
if (n.category == 'Output') {
|
|
p[n.name] = { name: n.showName, unit: n.unit }
|
|
}
|
|
return p
|
|
}, {})
|
|
}
|
|
sensorsId.push(id)
|
|
}
|
|
}
|
|
setDeviceId(deviceIds)
|
|
dispatch(analysis.getDevicesAlarms(deviceIds, { limit: 5 }, token))
|
|
setSensorsDataItems(sensorsDataItems)
|
|
setSensorId(sensorsId)
|
|
setDeviceData(da)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}, [thingId])
|
|
useEffect(async () => {
|
|
if (sensorId && sensorId.length && sensorsDataItems) {
|
|
const rs = await dispatch(analysis.findSensorLastData(sensorId, token))
|
|
const tableData = []
|
|
if (rs.success) {
|
|
rs.payload.data.forEach(sd => {
|
|
if (Object.keys(sensorsDataItems).length) {
|
|
let sensorDataItem = sensorsDataItems[sd.sensorId]
|
|
let sensorName = sensorDataItem && sensorDataItem.deviceName ? sensorDataItem.deviceName : ''
|
|
let msg = sd.data.length
|
|
? sd.data[0]
|
|
: {
|
|
collectTime: null,
|
|
sensorName: sensorName,
|
|
data: { noData: '暂无数据' },
|
|
}
|
|
let dataStr = ''
|
|
let dataKeys = Object.keys(msg.data)
|
|
dataKeys.forEach(k => {
|
|
let item = sensorDataItem && sensorDataItem.items ? sensorDataItem.items[k] : null
|
|
if (item) {
|
|
dataStr += `${item.name}:${msg.data[k]}(${item.unit}); `
|
|
} else if (k == 'noData') {
|
|
dataStr += msg.data[k]
|
|
} else {
|
|
dataStr += `${k}:${msg.data[k]};`
|
|
}
|
|
})
|
|
let collectTime = msg.collectTime ? moment(msg.collectTime).format('YYYY-MM-DD HH:mm:ss') : '--'
|
|
tableData.push({
|
|
sensorId: sd.sensorId,
|
|
sensorName: sensorName,
|
|
collectTime: collectTime,
|
|
model:sensorsDataItems[sd.sensorId]?.model,
|
|
searchId:sensorsDataItems[sd.sensorId]?.searchId,
|
|
controlId:sensorsDataItems[sd.sensorId]?.controlId,
|
|
data: dataStr,
|
|
deviceType: 'sensor', //传感器
|
|
iotCardStatus: '--',
|
|
status: '--',
|
|
option: '--',
|
|
})
|
|
}
|
|
})
|
|
}
|
|
setTableData(tableData)
|
|
}
|
|
}, [sensorId])
|
|
useEffect(() => {
|
|
if(deviceId&&deviceId.length&&tableData&&tableData.length){
|
|
dispatch(analysis.findDevicesCardStatus({ deviceIds: deviceId }, token))
|
|
.then(res=>{
|
|
if(res.success){
|
|
if (deviceData && deviceData.length&&tableData&&tableData.length) {
|
|
const dataD = deviceData?.map(p => {
|
|
const objRslt = tableData?.find(q => q.sensorId == p.sensorId)
|
|
return {
|
|
sensorId: objRslt ? objRslt.sensorId : p.sensorId,
|
|
sensorName: objRslt ? objRslt.sensorName : p.sensorName,
|
|
collectTime: objRslt ? objRslt.collectTime : p.collectTime,
|
|
data: objRslt ? objRslt.data : p.data,
|
|
deviceType: DeviceTypes[objRslt ? objRslt.deviceType : p.deviceType],
|
|
model:objRslt?objRslt?.model:p.model,
|
|
searchId:objRslt?objRslt.searchId:'',
|
|
controlId:objRslt?objRslt.controlId:'',
|
|
iotCardStatus:
|
|
res.payload.data && res.payload.data.length&&res.payload.data.find(v => v.deviceId == p.sensorId)?.status === 0
|
|
? '正常'
|
|
: res.payload.data.find(v => v.deviceId == p.sensorId)?.status === 1
|
|
? '未激活':res.payload.data.find(v => v.deviceId == p.sensorId)?.status === 2?'停机'
|
|
: '--',
|
|
status:
|
|
thingStatus && thingStatus.length
|
|
? thingStatus?.find(v => v.deviceId == p.sensorId)?.status===1?'在线':thingStatus?.find(v => v.deviceId == p.sensorId)?.status===0?'离线':'未知':'--',
|
|
|
|
option: objRslt ? objRslt.option : p.option,
|
|
}
|
|
})
|
|
const typeList = dataD.reduce((p, c) => {
|
|
let isExist = p.some(q => q.label === c.deviceType)
|
|
if (!isExist) {
|
|
p.push({ label: c.deviceType, value: c.sensorId })
|
|
}
|
|
return p
|
|
}, [])
|
|
setTypeList(typeList)
|
|
setLastData(dataD)
|
|
setLoading(false)
|
|
setLastDataCopy(dataD)
|
|
}
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
|
|
|
|
}, [deviceData,tableData,deviceId])
|
|
// const lastDataCopy=useMemo(()=>{
|
|
// return lastData
|
|
// },[thingId])
|
|
const scroll = useMemo(() => ({ y: clientHeight - 600 + 175 + 175 }), [])
|
|
//名称回调事件
|
|
const inputChange = e => {
|
|
setSearchName(e.target.value)
|
|
}
|
|
//选择设备类型下拉框回调
|
|
const selectChange = e => {
|
|
let rslt = typeList.find(f => f.value == e)
|
|
setSearchType(rslt ? rslt.label : undefined)
|
|
}
|
|
|
|
//查询事件回调
|
|
const searchHandler = () => {
|
|
setLastData(
|
|
lastDataCopy.filter(f =>
|
|
(!searchName || f.sensorName.includes(searchName)) &&
|
|
(!searchType || f.deviceType === searchType)
|
|
)
|
|
)
|
|
}
|
|
const searchStatusHandler=async (record)=>{
|
|
setControlId(record.controlId)
|
|
setId(record.sensorId)
|
|
setModalVis(true)
|
|
let dimensionId = null
|
|
let dtuId = null
|
|
const values = {
|
|
thingId,
|
|
deviceId: record.sensorId,
|
|
dimensionId,
|
|
dimCapId:record.searchId,
|
|
timeout: 60000 * 5,
|
|
// param,
|
|
// userId: user.id,
|
|
dtuId,
|
|
};
|
|
|
|
const res= await dispatch(analysis.invokeCapability(values,token))
|
|
setStatus(res?.payload?.data?.data?.data?.info?.includes('离线')?false:true)
|
|
form.setFieldValue('status', res?.payload?.data?.data?.data?.info)
|
|
}
|
|
const columns = [
|
|
{
|
|
title: '设备名称',
|
|
dataIndex: 'sensorName',
|
|
width: '20%',
|
|
key: 'sensorName',
|
|
render: (_, r) => {
|
|
return (
|
|
<>
|
|
<Tooltip title={r.sensorName}>
|
|
<div>{r.sensorName.length > 7 ? `${r.sensorName.substr(0, 7)}...` : r.sensorName}</div>
|
|
</Tooltip>
|
|
</>
|
|
)
|
|
},
|
|
},
|
|
{
|
|
title: '设备类型',
|
|
dataIndex: 'deviceType',
|
|
width: '15%',
|
|
key: 'deviceType',
|
|
},
|
|
{
|
|
title: '最后采集时间',
|
|
dataIndex: 'collectTime',
|
|
width: '15%',
|
|
key: 'collectTime',
|
|
},
|
|
{
|
|
title: '数据',
|
|
dataIndex: 'data',
|
|
width: '20%',
|
|
key: 'data',
|
|
render: (_, r) => {
|
|
return (
|
|
<>
|
|
<Tooltip title={r.data}>
|
|
<div>{r.data.length > 6 ? `${r.data.substr(0, 6)}...` : r.data}</div>
|
|
</Tooltip>
|
|
</>
|
|
)
|
|
},
|
|
},
|
|
{
|
|
title: '物联网卡状态',
|
|
width: '15%',
|
|
dataIndex: 'iotCardStatus',
|
|
key: 'iotCardStatus',
|
|
},
|
|
{
|
|
title: '状态',
|
|
width: '10%',
|
|
dataIndex: 'status',
|
|
key: 'status',
|
|
},
|
|
{
|
|
title: '操作',
|
|
width: '10%',
|
|
// dataIndex: 'option',
|
|
key: 'option',
|
|
render: (_, r) => {
|
|
return (
|
|
//E9C,FS-WSD-01M
|
|
<div> {r.model==='E9C'?<Button onClick={()=>{searchStatusHandler(r)}}>查询</Button>: '--'}</div>
|
|
)
|
|
}
|
|
},
|
|
]
|
|
const switchChange=(e)=>{
|
|
if(e){
|
|
setParam('开')
|
|
}else{
|
|
setParam('关')
|
|
}
|
|
}
|
|
//升级按钮
|
|
const okHandler=()=>{
|
|
let dimensionId = null
|
|
let dtuId = null
|
|
const values = {
|
|
thingId,
|
|
deviceId: id,
|
|
dimensionId,
|
|
dimCapId:controlId,
|
|
timeout: 60000 * 5,
|
|
param,
|
|
// userId: user.id,
|
|
dtuId,
|
|
};
|
|
|
|
dispatch(analysis.invokeCapability(values,token))
|
|
|
|
}
|
|
return (
|
|
<>
|
|
<Spin spinning={loading}>
|
|
<div style={{ marginBottom: 12, display: 'flex' }}>
|
|
<div>
|
|
<Input // suffix={<IconSearch />}
|
|
label='名称'
|
|
placeholder='请输入设备名称'
|
|
pure
|
|
allowClear
|
|
style={{ width: 260, marginRight: 12 }}
|
|
onChange={inputChange} />
|
|
<Select options={typeList} label='设备类型'
|
|
pure
|
|
allowClear
|
|
onChange={selectChange}
|
|
style={{ width: 260, marginLeft: 12, marginRight: 12 }}
|
|
placeholder='请选择设备类型'></Select>
|
|
<Button theme='solid' type='primary' htmlType='submit' onClick={searchHandler}>
|
|
查询
|
|
</Button>
|
|
</div>
|
|
<div style={{ marginLeft: 10 }}>
|
|
{' '}
|
|
{lastData.length ? (
|
|
<ExportData
|
|
// showIcon
|
|
fileName='设备列表'
|
|
exportType='fileSaver'
|
|
data={lastData}
|
|
columns={columns}
|
|
key='export'
|
|
/>
|
|
) : (
|
|
''
|
|
)}
|
|
</div>
|
|
</div>
|
|
<Table
|
|
// scroll={scroll}
|
|
columns={columns}
|
|
dataSource={lastData}></Table>
|
|
<Modal
|
|
title='开关'
|
|
footer={[ <Button key="back" onClick={()=>{setModalVis(false)}}>
|
|
取消
|
|
</Button>,
|
|
<Button key="submit" type="primary" disabled={!status} onClick={okHandler}>
|
|
下发指令
|
|
</Button>]}
|
|
visible={modalVis}
|
|
// sensorId={sensorId}
|
|
okText='升级'
|
|
>
|
|
<Form
|
|
form={form}
|
|
>
|
|
<Form.Item label='状态' name='status'>
|
|
<Input disabled />
|
|
</Form.Item>
|
|
<Form.Item label='开关' name='open'>
|
|
<Switch disabled={!status} onChange={switchChange}></Switch>
|
|
</Form.Item>
|
|
</Form>
|
|
</Modal>
|
|
</Spin>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function mapStateToProps (state) {
|
|
const { auth, global, members, webSocket, deviceListAlarms, devicesCardStatus,thingStatus } = state
|
|
return {
|
|
user: auth.user,
|
|
actions: global.actions,
|
|
clientHeight: global.clientHeight,
|
|
deviceListAlarms: deviceListAlarms?.data || [],
|
|
devicesCardStatusList: devicesCardStatus?.data || [],
|
|
thingStatus:thingStatus?.data||[]
|
|
|
|
}
|
|
}
|
|
|
|
export default connect(mapStateToProps)(Network)
|
|
|