diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index c7d5c18..ce0fb31 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -29,7 +29,7 @@ "-r fs-workflow", // "-e http://10.8.30.60:5601", // "--iotaProxy http://10.8.30.157:17007", - "--iotaProxy http://iotaproxy.anxinyun.cn", //商用 + "--iotaProxy https://iotaproxy.anxinyun.cn", //商用 // "--redisHost localhost", "--redisPort 6379", diff --git a/api/app/lib/controllers/analysis/network.js b/api/app/lib/controllers/analysis/network.js index ac78f06..8b3d99c 100644 --- a/api/app/lib/controllers/analysis/network.js +++ b/api/app/lib/controllers/analysis/network.js @@ -422,24 +422,17 @@ async function findAlarmsDevice (ctx, next) { ctx.body = rslt; } } -//查询智能 +//查询智能,以及空开设备的开关 async function createInvoke (ctx, next) { let error = { name: 'CreateError', message: '命令下发失败' }; const data = ctx.request.body - let rslt = null, code = null, issuccess = false, text = null; + let rslt = null if (data) { try { - const models = ctx.fs.dc.models; - let iotaThingId = data.thingId; - let structure = await models.Structure.findOne({ where: { iotaThingId } }); - if (structure) { - const dataToIota = data; + const dataToIota = data let iotaResponse = await ctx.app.fs.iotRequest.post(`/capabilities/invoke`, dataToIota) rslt = JSON.parse(iotaResponse) error = null; - } else { - error = { name: 'NotFound', message: `不存在{iotaThingId=${iotaThingId}}的结构物` }; - } } catch (err) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${err}`); } diff --git a/api/app/lib/routes/analysis/network.js b/api/app/lib/routes/analysis/network.js index 4e32ef6..9a4922c 100644 --- a/api/app/lib/routes/analysis/network.js +++ b/api/app/lib/routes/analysis/network.js @@ -34,4 +34,8 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/thing/status'] = { content: '获取设备在离线', visible: true }; router.get('/thing/status', network.getThingStatus); + + //空开设备查询状态和开关设备 + app.fs.api.logAttr['POST/capabilities/invoke'] = { content: '及时采集', visible: true }; + router.post('/capabilities/invoke', network.createInvoke); } \ No newline at end of file diff --git a/web-network/client/src/sections/network/actions/network.js b/web-network/client/src/sections/network/actions/network.js index 557e95a..5d687e2 100644 --- a/web-network/client/src/sections/network/actions/network.js +++ b/web-network/client/src/sections/network/actions/network.js @@ -153,6 +153,22 @@ export function getThingStatus (query, token) { } +export function invokeCapability(capabilityData,token) { + return dispatch => basicAction({ + type: 'post', + data: capabilityData, + dispatch: dispatch, + actionType: 'REQUEST_INVOKE_CAPABILITY', + url: `${ApiTable.invokeCapability}?token=${token}`, + msg: { + error: '命令下发失败' + }, + reducer: { + name: 'invokeCapability' + } + }); +} + export default { getOrganizationsStruc, @@ -166,6 +182,7 @@ export default { findDevicesCardStatus, getDevicesLlinkStatus, findAlarmsDevice, - getThingStatus + getThingStatus, + invokeCapability } diff --git a/web-network/client/src/sections/network/containers/tableShow.js b/web-network/client/src/sections/network/containers/tableShow.js index 5081f66..15a663c 100644 --- a/web-network/client/src/sections/network/containers/tableShow.js +++ b/web-network/client/src/sections/network/containers/tableShow.js @@ -1,11 +1,11 @@ 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 } from 'antd' +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, } = props + const { dispatch, actions, user, clientHeight, thingId, deviceListAlarms, devicesCardStatusList, project, token,thingStatus } = props const { analysis } = actions const form = useRef() //表单 const [deployData, setDeployData] = useState([]) @@ -19,10 +19,13 @@ const Network = props => { const [searchType, setSearchType] = useState('') const [searchName, setSearchName] = useState('') const [typeList, setTypeList] = useState([]) - const [query, setQuery] = useState({ limit: 10, page: 0 }) //页码信息 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 DeviceTypes = { 'DTU': 'DTU', 'gateway': '网关', @@ -72,16 +75,35 @@ const Network = props => { 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 + 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) => { @@ -140,6 +162,8 @@ const Network = props => { sensorName: sensorName, collectTime: collectTime, model:sensorsDataItems[sd.sensorId]?.model, + searchId:sensorsDataItems[sd.sensorId]?.searchId, + controlId:sensorsDataItems[sd.sensorId]?.controlId, data: dataStr, deviceType: 'sensor', //传感器 iotCardStatus: '--', @@ -167,6 +191,8 @@ const Network = props => { 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 ? '正常' @@ -174,11 +200,9 @@ const Network = props => { ? '未激活':res.payload.data.find(v => v.deviceId == p.sensorId)?.status === 2?'停机' : '--', status: - deviceListAlarms && deviceListAlarms.length - ? deviceListAlarms?.find(v => v.deviceId == p.sensorId) - ? '异常' - : '正常' - : '--', + 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, } }) @@ -225,7 +249,26 @@ const Network = props => { ) ) } + 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?.info?.includes('离线')?false:true) + } const columns = [ { title: '设备名称', @@ -289,11 +332,36 @@ const Network = props => { render: (_, r) => { return ( //E9C,FS-WSD-01M -