|
@@ -6,75 +6,109 @@
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
<el-tabs v-model="activeTab" type="border-card">
|
|
<el-tabs v-model="activeTab" type="border-card">
|
|
|
<!-- 上行指令调试 -->
|
|
<!-- 上行指令调试 -->
|
|
|
- <el-tab-pane label="上行指令调试" name="up">
|
|
|
|
|
- <el-tabs v-if="activeTab === 'up'" v-model="subTab">
|
|
|
|
|
|
|
+ <el-tab-pane label="上行指令调试" name="upstream">
|
|
|
|
|
+ <el-tabs v-if="activeTab === 'upstream'" v-model="upstreamTab">
|
|
|
<!-- 属性上报 -->
|
|
<!-- 属性上报 -->
|
|
|
- <el-tab-pane label="属性上报" name="property">
|
|
|
|
|
|
|
+ <el-tab-pane label="属性上报" :name="IotDeviceMessageMethodEnum.PROPERTY_POST.method">
|
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
|
- <el-table
|
|
|
|
|
- v-loading="loading"
|
|
|
|
|
- :data="list"
|
|
|
|
|
- :show-overflow-tooltip="true"
|
|
|
|
|
- :stripe="true"
|
|
|
|
|
- >
|
|
|
|
|
- <!-- TODO @super:每个 colum 搞下宽度,避免 table 每一列最后有个 . -->
|
|
|
|
|
- <!-- TODO @super:可以左侧 fixed -->
|
|
|
|
|
- <el-table-column align="center" label="功能名称" prop="name" />
|
|
|
|
|
- <el-table-column align="center" label="标识符" prop="identifier" />
|
|
|
|
|
- <el-table-column align="center" label="数据类型" prop="identifier">
|
|
|
|
|
- <!-- TODO @super:不用翻译,可以减少宽度的占用 -->
|
|
|
|
|
|
|
+ <el-table :data="propertyList" :show-overflow-tooltip="true" :stripe="true">
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ fixed="left"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ label="功能名称"
|
|
|
|
|
+ prop="name"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ fixed="left"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ label="标识符"
|
|
|
|
|
+ prop="identifier"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column align="center" label="数据类型" width="100">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- {{ dataTypeOptionsLabel(row.property?.dataType) ?? '-' }}
|
|
|
|
|
|
|
+ {{ row.property?.dataType ?? '-' }}
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column align="left" label="数据定义" prop="identifier">
|
|
|
|
|
|
|
+ <el-table-column align="left" label="数据定义" min-width="200">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
<DataDefinition :data="row" />
|
|
<DataDefinition :data="row" />
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <!-- TODO @super:可以右侧 fixed -->
|
|
|
|
|
- <el-table-column align="center" label="值" width="80">
|
|
|
|
|
|
|
+ <el-table-column fixed="right" align="center" label="值" width="150">
|
|
|
<template #default="scope">
|
|
<template #default="scope">
|
|
|
- <el-input v-model="scope.row.simulateValue" class="!w-60px" />
|
|
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ :model-value="getFormValue(scope.row.identifier)"
|
|
|
|
|
+ @update:model-value="setFormValue(scope.row.identifier, $event)"
|
|
|
|
|
+ placeholder="输入值"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</el-table>
|
|
</el-table>
|
|
|
- <!-- TODO @super:发送按钮,可以放在右侧哈。因为我们的 simulateValue 就在最右侧 -->
|
|
|
|
|
- <div class="mt-10px">
|
|
|
|
|
- <el-button type="primary" @click="handlePropertyReport"> 发送</el-button>
|
|
|
|
|
|
|
+ <div class="flex justify-between items-center mt-4">
|
|
|
|
|
+ <span class="text-sm text-gray-600">
|
|
|
|
|
+ 设置属性值后,点击「发送属性上报」按钮
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <el-button type="primary" @click="handlePropertyPost">发送属性上报</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</ContentWrap>
|
|
</ContentWrap>
|
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
<!-- 事件上报 -->
|
|
<!-- 事件上报 -->
|
|
|
- <!-- TODO @super:待实现 -->
|
|
|
|
|
- <el-tab-pane label="事件上报" name="event">
|
|
|
|
|
|
|
+ <el-tab-pane label="事件上报" :name="IotDeviceMessageMethodEnum.EVENT_POST.method">
|
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
|
- <!-- TODO @super:因为事件是每个 event 去模拟,而不是类似属性的批量上传。所以,可以每一列后面有个“模拟”按钮。另外,“值”使用 textarea,高度 3 -->
|
|
|
|
|
- <!-- <el-table v-loading="loading" :data="eventList" :stripe="true">
|
|
|
|
|
- <el-table-column label="功能名称" align="center" prop="name" />
|
|
|
|
|
- <el-table-column label="标识符" align="center" prop="identifier" />
|
|
|
|
|
- <el-table-column label="数据类型" align="center" prop="dataType" />
|
|
|
|
|
|
|
+ <el-table :data="eventList" :show-overflow-tooltip="true" :stripe="true">
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
- label="数据定义"
|
|
|
|
|
|
|
+ fixed="left"
|
|
|
align="center"
|
|
align="center"
|
|
|
- prop="specs"
|
|
|
|
|
- :show-overflow-tooltip="true"
|
|
|
|
|
|
|
+ label="功能名称"
|
|
|
|
|
+ prop="name"
|
|
|
|
|
+ width="120"
|
|
|
/>
|
|
/>
|
|
|
- <el-table-column label="值" align="center" width="80">
|
|
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ fixed="left"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ label="标识符"
|
|
|
|
|
+ prop="identifier"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column align="center" label="数据类型" width="100">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ {{ row.event?.dataType ?? '-' }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column align="left" label="数据定义" min-width="200">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <DataDefinition :data="row" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column align="center" label="值" width="200">
|
|
|
<template #default="scope">
|
|
<template #default="scope">
|
|
|
- <el-input v-model="scope.row.simulateValue" class="!w-60px" />
|
|
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ :model-value="getFormValue(scope.row.identifier)"
|
|
|
|
|
+ @update:model-value="setFormValue(scope.row.identifier, $event)"
|
|
|
|
|
+ type="textarea"
|
|
|
|
|
+ :rows="3"
|
|
|
|
|
+ placeholder="输入事件参数(JSON格式)"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column fixed="right" align="center" label="操作" width="100">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-button type="primary" size="small" @click="handleEventPost(scope.row)">
|
|
|
|
|
+ 上报事件
|
|
|
|
|
+ </el-button>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</el-table>
|
|
</el-table>
|
|
|
- <div class="mt-10px">
|
|
|
|
|
- <el-button type="primary" @click="handleEventReport">发送</el-button>
|
|
|
|
|
- </div> -->
|
|
|
|
|
</ContentWrap>
|
|
</ContentWrap>
|
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
<!-- 状态变更 -->
|
|
<!-- 状态变更 -->
|
|
|
- <el-tab-pane label="状态变更" name="status">
|
|
|
|
|
|
|
+ <el-tab-pane label="状态变更" :name="IotDeviceMessageMethodEnum.STATE_UPDATE.method">
|
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
|
<div class="flex gap-4">
|
|
<div class="flex gap-4">
|
|
|
<el-button type="primary" @click="handleDeviceState(DeviceStateEnum.ONLINE)">
|
|
<el-button type="primary" @click="handleDeviceState(DeviceStateEnum.ONLINE)">
|
|
@@ -90,39 +124,106 @@
|
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
<!-- 下行指令调试 -->
|
|
<!-- 下行指令调试 -->
|
|
|
- <!-- TODO @super:待实现 -->
|
|
|
|
|
- <el-tab-pane label="下行指令调试" name="down">
|
|
|
|
|
- <el-tabs v-if="activeTab === 'down'" v-model="subTab">
|
|
|
|
|
|
|
+ <el-tab-pane label="下行指令调试" name="downstream">
|
|
|
|
|
+ <el-tabs v-if="activeTab === 'downstream'" v-model="downstreamTab">
|
|
|
<!-- 属性调试 -->
|
|
<!-- 属性调试 -->
|
|
|
- <el-tab-pane label="属性调试" name="propertyDebug">
|
|
|
|
|
|
|
+ <el-tab-pane label="属性设置" :name="IotDeviceMessageMethodEnum.PROPERTY_SET.method">
|
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
|
- <!-- <el-table v-loading="loading" :data="propertyList" :stripe="true">
|
|
|
|
|
- <el-table-column label="功能名称" align="center" prop="name" />
|
|
|
|
|
- <el-table-column label="标识符" align="center" prop="identifier" />
|
|
|
|
|
- <el-table-column label="数据类型" align="center" prop="dataType" />
|
|
|
|
|
|
|
+ <el-table :data="propertyList" :show-overflow-tooltip="true" :stripe="true">
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
- label="数据定义"
|
|
|
|
|
|
|
+ fixed="left"
|
|
|
align="center"
|
|
align="center"
|
|
|
- prop="specs"
|
|
|
|
|
- :show-overflow-tooltip="true"
|
|
|
|
|
|
|
+ label="功能名称"
|
|
|
|
|
+ prop="name"
|
|
|
|
|
+ width="120"
|
|
|
/>
|
|
/>
|
|
|
- <el-table-column label="值" align="center" width="80">
|
|
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ fixed="left"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ label="标识符"
|
|
|
|
|
+ prop="identifier"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column align="center" label="数据类型" width="100">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ {{ row.property?.dataType ?? '-' }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column align="left" label="数据定义" min-width="200">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <DataDefinition :data="row" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column fixed="right" align="center" label="值" width="150">
|
|
|
<template #default="scope">
|
|
<template #default="scope">
|
|
|
- <el-input v-model="scope.row.simulateValue" class="!w-60px" />
|
|
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ :model-value="getFormValue(scope.row.identifier)"
|
|
|
|
|
+ @update:model-value="setFormValue(scope.row.identifier, $event)"
|
|
|
|
|
+ placeholder="输入值"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</el-table>
|
|
</el-table>
|
|
|
- <div class="mt-10px">
|
|
|
|
|
- <el-button type="primary" @click="handlePropertyGet">获取</el-button>
|
|
|
|
|
- </div> -->
|
|
|
|
|
|
|
+ <div class="flex justify-between items-center mt-4">
|
|
|
|
|
+ <span class="text-sm text-gray-600">
|
|
|
|
|
+ 设置属性值后,点击「发送属性设置」按钮
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <el-button type="primary" @click="handlePropertySet">发送属性设置</el-button>
|
|
|
|
|
+ </div>
|
|
|
</ContentWrap>
|
|
</ContentWrap>
|
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
<!-- 服务调用 -->
|
|
<!-- 服务调用 -->
|
|
|
- <!-- TODO @super:待实现 -->
|
|
|
|
|
- <el-tab-pane label="服务调用" name="service">
|
|
|
|
|
|
|
+ <el-tab-pane
|
|
|
|
|
+ label="设备服务调用"
|
|
|
|
|
+ :name="IotDeviceMessageMethodEnum.SERVICE_INVOKE.method"
|
|
|
|
|
+ >
|
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
|
- <!-- 服务调用相关内容 -->
|
|
|
|
|
|
|
+ <el-table :data="serviceList" :show-overflow-tooltip="true" :stripe="true">
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ fixed="left"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ label="服务名称"
|
|
|
|
|
+ prop="name"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ fixed="left"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ label="标识符"
|
|
|
|
|
+ prop="identifier"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column align="left" label="输入参数" min-width="200">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <DataDefinition :data="row" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column align="center" label="参数值" width="200">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ :model-value="getFormValue(scope.row.identifier)"
|
|
|
|
|
+ @update:model-value="setFormValue(scope.row.identifier, $event)"
|
|
|
|
|
+ type="textarea"
|
|
|
|
|
+ :rows="3"
|
|
|
|
|
+ placeholder="输入服务参数(JSON格式)"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column fixed="right" align="center" label="操作" width="100">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ @click="handleServiceInvoke(scope.row)"
|
|
|
|
|
+ >
|
|
|
|
|
+ 服务调用
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
</ContentWrap>
|
|
</ContentWrap>
|
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
</el-tabs>
|
|
</el-tabs>
|
|
@@ -132,11 +233,9 @@
|
|
|
|
|
|
|
|
<!-- 右侧设备日志区域 -->
|
|
<!-- 右侧设备日志区域 -->
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
- <el-tabs type="border-card">
|
|
|
|
|
- <el-tab-pane label="设备日志">
|
|
|
|
|
- <DeviceDetailsLog :device-key="device.deviceKey" />
|
|
|
|
|
- </el-tab-pane>
|
|
|
|
|
- </el-tabs>
|
|
|
|
|
|
|
+ <ContentWrap title="设备消息">
|
|
|
|
|
+ <DeviceDetailsMessage ref="deviceMessageRef" :device-id="device.id" />
|
|
|
|
|
+ </ContentWrap>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
</el-row>
|
|
</el-row>
|
|
|
</ContentWrap>
|
|
</ContentWrap>
|
|
@@ -144,188 +243,178 @@
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
|
import { ProductVO } from '@/api/iot/product/product'
|
|
import { ProductVO } from '@/api/iot/product/product'
|
|
|
-import { SimulatorData, ThingModelApi } from '@/api/iot/thingmodel'
|
|
|
|
|
|
|
+import { ThingModelData } from '@/api/iot/thingmodel'
|
|
|
import { DeviceApi, DeviceStateEnum, DeviceVO } from '@/api/iot/device/device'
|
|
import { DeviceApi, DeviceStateEnum, DeviceVO } from '@/api/iot/device/device'
|
|
|
-import DeviceDetailsLog from './DeviceDetailsLog.vue'
|
|
|
|
|
-import { getDataTypeOptionsLabel } from '@/views/iot/thingmodel/config'
|
|
|
|
|
|
|
+import DeviceDetailsMessage from './DeviceDetailsMessage.vue'
|
|
|
import { DataDefinition } from '@/views/iot/thingmodel/components'
|
|
import { DataDefinition } from '@/views/iot/thingmodel/components'
|
|
|
|
|
+import { IotDeviceMessageMethodEnum, IoTThingModelTypeEnum } from '@/views/iot/utils/constants'
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
const props = defineProps<{
|
|
|
product: ProductVO
|
|
product: ProductVO
|
|
|
device: DeviceVO
|
|
device: DeviceVO
|
|
|
|
|
+ thingModelList: ThingModelData[]
|
|
|
}>()
|
|
}>()
|
|
|
|
|
|
|
|
const message = useMessage() // 消息弹窗
|
|
const message = useMessage() // 消息弹窗
|
|
|
-const activeTab = ref('up') // TODO @super:upstream 上行、downstream 下行
|
|
|
|
|
-const subTab = ref('property') // TODO @super:upstreamTab
|
|
|
|
|
|
|
+const activeTab = ref('upstream') // 上行upstream、下行downstream
|
|
|
|
|
+const upstreamTab = ref(IotDeviceMessageMethodEnum.PROPERTY_POST.method) // 上行子标签
|
|
|
|
|
+const downstreamTab = ref(IotDeviceMessageMethodEnum.PROPERTY_SET.method) // 下行子标签
|
|
|
|
|
+const deviceMessageRef = ref() // 设备消息组件引用
|
|
|
|
|
+const deviceMessageRefreshDelay = 2000 // 延迟 N 秒,保证模拟上行的消息被处理
|
|
|
|
|
|
|
|
-const loading = ref(false)
|
|
|
|
|
-const queryParams = reactive({
|
|
|
|
|
- type: undefined, // TODO @super:type 默认给个第一个 tab 对应的,避免下面 watch 爆红
|
|
|
|
|
- productId: -1
|
|
|
|
|
-})
|
|
|
|
|
-const list = ref<SimulatorData[]>([]) // 物模型列表的数据 TODO @super:thingModelList
|
|
|
|
|
-// TODO @super:dataTypeOptionsLabel 是不是不用定义,直接用 getDataTypeOptionsLabel 在 template 中使用即可?
|
|
|
|
|
-const dataTypeOptionsLabel = computed(() => (value: string) => getDataTypeOptionsLabel(value)) // 解析数据类型
|
|
|
|
|
|
|
+// 表单数据:存储用户输入的模拟值
|
|
|
|
|
+const formData = ref<Record<string, string>>({})
|
|
|
|
|
|
|
|
-/** 查询物模型列表 */
|
|
|
|
|
-// TODO @super:getThingModelList 更精准
|
|
|
|
|
-const getList = async () => {
|
|
|
|
|
- loading.value = true
|
|
|
|
|
- try {
|
|
|
|
|
- queryParams.productId = props.product?.id || -1
|
|
|
|
|
- const data = await ThingModelApi.getThingModelList(queryParams)
|
|
|
|
|
- // 转换数据,添加 simulateValue 字段
|
|
|
|
|
- // TODO @super:貌似下面的 simulateValue 不设置也可以?
|
|
|
|
|
- list.value = data.map((item) => ({
|
|
|
|
|
- ...item,
|
|
|
|
|
- simulateValue: ''
|
|
|
|
|
- }))
|
|
|
|
|
- } finally {
|
|
|
|
|
- loading.value = false
|
|
|
|
|
- }
|
|
|
|
|
|
|
+// 根据类型过滤物模型数据
|
|
|
|
|
+const getFilteredThingModelList = (type: number) => {
|
|
|
|
|
+ return props.thingModelList.filter((item) => item.type === type)
|
|
|
}
|
|
}
|
|
|
|
|
+const propertyList = computed(() => getFilteredThingModelList(IoTThingModelTypeEnum.PROPERTY))
|
|
|
|
|
+const eventList = computed(() => getFilteredThingModelList(IoTThingModelTypeEnum.EVENT))
|
|
|
|
|
+const serviceList = computed(() => getFilteredThingModelList(IoTThingModelTypeEnum.SERVICE))
|
|
|
|
|
|
|
|
-// // 功能列表数据结构定义
|
|
|
|
|
-// interface TableItem {
|
|
|
|
|
-// name: string
|
|
|
|
|
-// identifier: string
|
|
|
|
|
-// value: string | number
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-// // 添加计算属性来过滤物模型数据
|
|
|
|
|
-// const propertyList = computed(() => {
|
|
|
|
|
-// return list.value
|
|
|
|
|
-// .filter((item) => item.type === 'property')
|
|
|
|
|
-// .map((item) => ({
|
|
|
|
|
-// name: item.name,
|
|
|
|
|
-// identifier: item.identifier,
|
|
|
|
|
-// value: ''
|
|
|
|
|
-// }))
|
|
|
|
|
-// })
|
|
|
|
|
-
|
|
|
|
|
-// const eventList = computed(() => {
|
|
|
|
|
-// return list.value
|
|
|
|
|
-// .filter((item) => item.type === 'event')
|
|
|
|
|
-// .map((item) => ({
|
|
|
|
|
-// name: item.name,
|
|
|
|
|
-// identifier: item.identifier,
|
|
|
|
|
-// value: ''
|
|
|
|
|
-// }))
|
|
|
|
|
-// })
|
|
|
|
|
-
|
|
|
|
|
-/** 监听标签页变化 */
|
|
|
|
|
-// todo:后续改成查询字典
|
|
|
|
|
-watch(
|
|
|
|
|
- [activeTab, subTab],
|
|
|
|
|
- ([newActiveTab, newSubTab]) => {
|
|
|
|
|
- // 根据标签页设置查询类型
|
|
|
|
|
- if (newActiveTab === 'up') {
|
|
|
|
|
- switch (newSubTab) {
|
|
|
|
|
- case 'property':
|
|
|
|
|
- queryParams.type = 1
|
|
|
|
|
- break
|
|
|
|
|
- case 'event':
|
|
|
|
|
- queryParams.type = 3
|
|
|
|
|
- break
|
|
|
|
|
- // case 'status':
|
|
|
|
|
- // queryParams.type = 'status'
|
|
|
|
|
- // break
|
|
|
|
|
- }
|
|
|
|
|
- } else if (newActiveTab === 'down') {
|
|
|
|
|
- switch (newSubTab) {
|
|
|
|
|
- case 'propertyDebug':
|
|
|
|
|
- queryParams.type = 1
|
|
|
|
|
- break
|
|
|
|
|
- case 'service':
|
|
|
|
|
- queryParams.type = 2
|
|
|
|
|
- break
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- getList() // 切换标签时重新获取数据
|
|
|
|
|
- },
|
|
|
|
|
- { immediate: true }
|
|
|
|
|
-)
|
|
|
|
|
|
|
+/** 获取表单值的辅助函数 */
|
|
|
|
|
+const getFormValue = (identifier: string | number | undefined) => {
|
|
|
|
|
+ if (!identifier) return ''
|
|
|
|
|
+ return formData.value[String(identifier)] || ''
|
|
|
|
|
+}
|
|
|
|
|
+/** 设置表单值的辅助函数 */
|
|
|
|
|
+const setFormValue = (identifier: string | number | undefined, value: string) => {
|
|
|
|
|
+ if (!identifier) return
|
|
|
|
|
+ formData.value[String(identifier)] = value
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-/** 处理属性上报 */
|
|
|
|
|
-const handlePropertyReport = async () => {
|
|
|
|
|
- // TODO @super:数据类型效验
|
|
|
|
|
- const data: Record<string, object> = {}
|
|
|
|
|
- list.value.forEach((item) => {
|
|
|
|
|
- // 只有当 simulateValue 有值时才添加到 content 中
|
|
|
|
|
- // TODO @super:直接 if (item.simulateValue) 就可以哈,js 这块还是比较灵活的
|
|
|
|
|
- if (item.simulateValue !== undefined && item.simulateValue !== '') {
|
|
|
|
|
- // TODO @super:这里有个红色的 idea 告警,觉得去除下
|
|
|
|
|
- data[item.identifier] = item.simulateValue
|
|
|
|
|
|
|
+/** 模拟属性上报 */
|
|
|
|
|
+const handlePropertyPost = async () => {
|
|
|
|
|
+ const data: Record<string, any> = {}
|
|
|
|
|
+ propertyList.value.forEach((item) => {
|
|
|
|
|
+ const value = getFormValue(item.identifier)
|
|
|
|
|
+ if (value && item.identifier) {
|
|
|
|
|
+ data[String(item.identifier)] = value
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
+ if (Object.keys(data).length === 0) {
|
|
|
|
|
+ message.warning('请至少设置一个属性值')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- await DeviceApi.upstreamDevice({
|
|
|
|
|
- id: props.device.id,
|
|
|
|
|
- type: 'property',
|
|
|
|
|
- identifier: 'report',
|
|
|
|
|
- data: data
|
|
|
|
|
|
|
+ await DeviceApi.sendDeviceMessage({
|
|
|
|
|
+ deviceId: props.device.id,
|
|
|
|
|
+ method: IotDeviceMessageMethodEnum.PROPERTY_POST.method,
|
|
|
|
|
+ params: data
|
|
|
})
|
|
})
|
|
|
message.success('属性上报成功')
|
|
message.success('属性上报成功')
|
|
|
|
|
+ deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
message.error('属性上报失败')
|
|
message.error('属性上报失败')
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// // 处理事件上报
|
|
|
|
|
-// const handleEventReport = async () => {
|
|
|
|
|
-// const contentObj: Record<string, any> = {}
|
|
|
|
|
-// list.value
|
|
|
|
|
-// .filter(item => item.type === 'event')
|
|
|
|
|
-// .forEach((item) => {
|
|
|
|
|
-// if (item.simulateValue !== undefined && item.simulateValue !== '') {
|
|
|
|
|
-// contentObj[item.identifier] = item.simulateValue
|
|
|
|
|
-// }
|
|
|
|
|
-// })
|
|
|
|
|
-
|
|
|
|
|
-// const reportData: ReportData = {
|
|
|
|
|
-// productKey: props.product.productKey,
|
|
|
|
|
-// deviceKey: props.device.deviceKey,
|
|
|
|
|
-// type: 'event',
|
|
|
|
|
-// subType: list.value.find(item => item.type === 'event')?.identifier || '',
|
|
|
|
|
-// reportTime: new Date().toISOString(),
|
|
|
|
|
-// content: JSON.stringify(contentObj) // 转换为 JSON 字符串
|
|
|
|
|
-// }
|
|
|
|
|
|
|
+/** 模拟事件上报 */
|
|
|
|
|
+const handleEventPost = async (eventItem: ThingModelData) => {
|
|
|
|
|
+ const value = getFormValue(eventItem.identifier)
|
|
|
|
|
+ if (!value) {
|
|
|
|
|
+ message.warning('请输入事件参数')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ let eventParams: any
|
|
|
|
|
+ try {
|
|
|
|
|
+ eventParams = JSON.parse(value)
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ message.error('事件参数格式不正确,请输入有效的JSON格式')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-// try {
|
|
|
|
|
-// // TODO: 调用API发送数据
|
|
|
|
|
-// console.log('上报数据:', reportData)
|
|
|
|
|
-// message.success('事件上报成功')
|
|
|
|
|
-// } catch (error) {
|
|
|
|
|
-// message.error('事件上报失败')
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ await DeviceApi.sendDeviceMessage({
|
|
|
|
|
+ deviceId: props.device.id,
|
|
|
|
|
+ method: IotDeviceMessageMethodEnum.EVENT_POST.method,
|
|
|
|
|
+ params: {
|
|
|
|
|
+ identifier: String(eventItem.identifier),
|
|
|
|
|
+ value: eventParams,
|
|
|
|
|
+ time: Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ message.success(`事件【${String(eventItem.name)}】上报成功`)
|
|
|
|
|
+ deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ message.error(`事件【${String(eventItem.name)}】上报失败`)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-/** 处理设备状态 */
|
|
|
|
|
|
|
+/** 模拟设备状态 */
|
|
|
const handleDeviceState = async (state: number) => {
|
|
const handleDeviceState = async (state: number) => {
|
|
|
try {
|
|
try {
|
|
|
- await DeviceApi.upstreamDevice({
|
|
|
|
|
- id: props.device.id,
|
|
|
|
|
- type: 'state',
|
|
|
|
|
- identifier: 'report',
|
|
|
|
|
- data: state
|
|
|
|
|
|
|
+ await DeviceApi.sendDeviceMessage({
|
|
|
|
|
+ deviceId: props.device.id,
|
|
|
|
|
+ method: IotDeviceMessageMethodEnum.STATE_UPDATE.method,
|
|
|
|
|
+ params: {
|
|
|
|
|
+ state: state
|
|
|
|
|
+ }
|
|
|
})
|
|
})
|
|
|
message.success(`设备${state === DeviceStateEnum.ONLINE ? '上线' : '下线'}成功`)
|
|
message.success(`设备${state === DeviceStateEnum.ONLINE ? '上线' : '下线'}成功`)
|
|
|
|
|
+ deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
message.error(`设备${state === DeviceStateEnum.ONLINE ? '上线' : '下线'}失败`)
|
|
message.error(`设备${state === DeviceStateEnum.ONLINE ? '上线' : '下线'}失败`)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 处理属性获取
|
|
|
|
|
-const handlePropertyGet = async () => {
|
|
|
|
|
- // TODO: 实现属性获取逻辑
|
|
|
|
|
- message.success('属性获取成功')
|
|
|
|
|
|
|
+/** 模拟属性设置 */
|
|
|
|
|
+const handlePropertySet = async () => {
|
|
|
|
|
+ const data: Record<string, any> = {}
|
|
|
|
|
+ propertyList.value.forEach((item) => {
|
|
|
|
|
+ const value = getFormValue(item.identifier)
|
|
|
|
|
+ if (value && item.identifier) {
|
|
|
|
|
+ data[String(item.identifier)] = value
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ if (Object.keys(data).length === 0) {
|
|
|
|
|
+ message.warning('请至少设置一个属性值')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ await DeviceApi.sendDeviceMessage({
|
|
|
|
|
+ deviceId: props.device.id,
|
|
|
|
|
+ method: IotDeviceMessageMethodEnum.PROPERTY_SET.method,
|
|
|
|
|
+ params: data
|
|
|
|
|
+ })
|
|
|
|
|
+ message.success('属性设置成功')
|
|
|
|
|
+ deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ message.error('属性设置失败')
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 初始化
|
|
|
|
|
-onMounted(() => {
|
|
|
|
|
- getList()
|
|
|
|
|
-})
|
|
|
|
|
-// TODO @芋艿:后续再详细 review 下;
|
|
|
|
|
|
|
+/** 模拟服务调用 */
|
|
|
|
|
+const handleServiceInvoke = async (serviceItem: ThingModelData) => {
|
|
|
|
|
+ const value = getFormValue(serviceItem.identifier)
|
|
|
|
|
+ if (!value) {
|
|
|
|
|
+ message.warning('请输入服务参数')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ let serviceParams: any
|
|
|
|
|
+ try {
|
|
|
|
|
+ serviceParams = JSON.parse(value)
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ message.error('服务参数格式不正确,请输入有效的JSON格式')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ await DeviceApi.sendDeviceMessage({
|
|
|
|
|
+ deviceId: props.device.id,
|
|
|
|
|
+ method: IotDeviceMessageMethodEnum.SERVICE_INVOKE.method,
|
|
|
|
|
+ params: {
|
|
|
|
|
+ identifier: String(serviceItem.identifier),
|
|
|
|
|
+ inputParams: serviceParams
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ message.success(`服务【${String(serviceItem.name)}】调用成功`)
|
|
|
|
|
+ deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ message.error(`服务【${String(serviceItem.name)}】调用失败`)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|