!858 feat(iot):【网关设备:80%】动态注册的初步实现(已测试)
Merge pull request !858 from 芋道源码/feature/iot-subpull/855/MERGE
commit
859d493513
|
|
@ -21,7 +21,6 @@ export interface DeviceVO {
|
|||
mqttClientId: string // MQTT 客户端 ID
|
||||
mqttUsername: string // MQTT 用户名
|
||||
mqttPassword: string // MQTT 密码
|
||||
authType: string // 认证类型
|
||||
latitude?: number // 设备位置的纬度
|
||||
longitude?: number // 设备位置的经度
|
||||
areaId: number // 地区编码
|
||||
|
|
@ -158,5 +157,28 @@ export const DeviceApi = {
|
|||
// 发送设备消息
|
||||
sendDeviceMessage: async (params: IotDeviceMessageSendReqVO) => {
|
||||
return await request.post({ url: `/iot/device/message/send`, data: params })
|
||||
},
|
||||
|
||||
// 绑定子设备到网关
|
||||
bindDeviceGateway: async (data: { subIds: number[]; gatewayId: number }) => {
|
||||
return await request.put({ url: `/iot/device/bind-gateway`, data })
|
||||
},
|
||||
|
||||
// 解绑子设备与网关
|
||||
unbindDeviceGateway: async (data: { subIds: number[]; gatewayId: number }) => {
|
||||
return await request.put({ url: `/iot/device/unbind-gateway`, data })
|
||||
},
|
||||
|
||||
// 获取网关的子设备列表
|
||||
getSubDeviceList: async (gatewayId: number) => {
|
||||
return await request.get<DeviceVO[]>({
|
||||
url: `/iot/device/sub-device-list`,
|
||||
params: { gatewayId }
|
||||
})
|
||||
},
|
||||
|
||||
// 获取未绑定网关的子设备分页
|
||||
getUnboundSubDevicePage: async (params: any) => {
|
||||
return await request.get({ url: `/iot/device/unbound-sub-device-page`, params })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ export interface ProductVO {
|
|||
id: number // 产品编号
|
||||
name: string // 产品名称
|
||||
productKey: string // 产品标识
|
||||
productSecret?: string // 产品密钥
|
||||
registerEnabled?: boolean // 动态注册
|
||||
protocolId: number // 协议编号
|
||||
categoryId: number // 产品所属品类标识符
|
||||
categoryName?: string // 产品所属品类名称
|
||||
|
|
@ -68,8 +70,8 @@ export const ProductApi = {
|
|||
},
|
||||
|
||||
// 查询产品(精简)列表
|
||||
getSimpleProductList() {
|
||||
return request.get({ url: '/iot/product/simple-list' })
|
||||
getSimpleProductList(deviceType?: number) {
|
||||
return request.get({ url: '/iot/product/simple-list', params: { deviceType } })
|
||||
},
|
||||
|
||||
// 根据 ProductKey 获取产品信息
|
||||
|
|
|
|||
|
|
@ -30,20 +30,6 @@
|
|||
:disabled="formType === 'update'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formData.deviceType === DeviceTypeEnum.GATEWAY_SUB"
|
||||
label="网关设备"
|
||||
prop="gatewayId"
|
||||
>
|
||||
<el-select v-model="formData.gatewayId" placeholder="子设备可选择父设备" clearable>
|
||||
<el-option
|
||||
v-for="gateway in gatewayDevices"
|
||||
:key="gateway.id"
|
||||
:label="gateway.nickname || gateway.deviceName"
|
||||
:value="gateway.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-collapse>
|
||||
<el-collapse-item title="更多配置">
|
||||
|
|
@ -114,7 +100,6 @@ const formData = ref({
|
|||
deviceName: undefined,
|
||||
nickname: undefined,
|
||||
picUrl: undefined,
|
||||
gatewayId: undefined,
|
||||
deviceType: undefined as number | undefined,
|
||||
serialNumber: undefined,
|
||||
longitude: undefined as number | string | undefined,
|
||||
|
|
@ -222,7 +207,6 @@ const formRules = reactive({
|
|||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const products = ref<ProductVO[]>([]) // 产品列表
|
||||
const gatewayDevices = ref<DeviceVO[]>([]) // 网关设备列表
|
||||
const deviceGroups = ref<any[]>([])
|
||||
|
||||
/** 打开弹窗 */
|
||||
|
|
@ -242,8 +226,6 @@ const open = async (type: string, id?: number) => {
|
|||
}
|
||||
}
|
||||
|
||||
// 加载网关设备列表
|
||||
gatewayDevices.value = await DeviceApi.getSimpleDeviceList(DeviceTypeEnum.GATEWAY)
|
||||
// 加载产品列表
|
||||
products.value = await ProductApi.getSimpleProductList()
|
||||
// 加载设备分组列表
|
||||
|
|
@ -283,7 +265,6 @@ const resetForm = () => {
|
|||
deviceName: undefined,
|
||||
nickname: undefined,
|
||||
picUrl: undefined,
|
||||
gatewayId: undefined,
|
||||
deviceType: undefined,
|
||||
serialNumber: undefined,
|
||||
longitude: undefined,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,264 @@
|
|||
<!-- 子设备管理 -->
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mb-4">
|
||||
<el-button type="primary" plain @click="openBindDialog" v-hasPermi="['iot:device:update']">
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 添加子设备
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="handleUnbindBatch"
|
||||
:disabled="selectedIds.length === 0"
|
||||
v-hasPermi="['iot:device:update']"
|
||||
>
|
||||
<Icon icon="ep:delete" class="mr-5px" /> 批量解绑
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 子设备列表 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="subDeviceList"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="DeviceName" align="center" prop="deviceName">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="openDeviceDetail(row.id)">{{ row.deviceName }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注名称" align="center" prop="nickname" />
|
||||
<el-table-column label="产品名称" align="center" prop="productName" />
|
||||
<el-table-column label="设备状态" align="center" prop="state">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="row.state" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="最后上线时间"
|
||||
align="center"
|
||||
prop="onlineTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="120px">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openDeviceDetail(row.id)"> 查看 </el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleUnbind(row.id)"
|
||||
v-hasPermi="['iot:device:update']"
|
||||
>
|
||||
解绑
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 添加子设备弹窗 -->
|
||||
<Dialog title="添加子设备" v-model="bindDialogVisible" width="900px">
|
||||
<ContentWrap>
|
||||
<!-- 搜索区域 -->
|
||||
<el-form :model="bindQueryParams" ref="bindQueryFormRef" :inline="true" class="-mb-15px">
|
||||
<el-form-item label="产品" prop="productId">
|
||||
<ProductSelect
|
||||
v-model="bindQueryParams.productId"
|
||||
:device-type="DeviceTypeEnum.GATEWAY_SUB"
|
||||
class="!w-200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备名称" prop="deviceName">
|
||||
<el-input
|
||||
v-model="bindQueryParams.deviceName"
|
||||
placeholder="请输入设备名称"
|
||||
clearable
|
||||
class="!w-200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="getBindableDevicePage">
|
||||
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||
</el-button>
|
||||
<el-button @click="resetBindQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<ContentWrap>
|
||||
<!-- 分页表格 -->
|
||||
<el-table
|
||||
ref="bindTableRef"
|
||||
v-loading="bindFormLoading"
|
||||
:data="bindableDevices"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
@selection-change="handleBindSelectionChange"
|
||||
max-height="400px"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="DeviceName" align="center" prop="deviceName" />
|
||||
<el-table-column label="备注名称" align="center" prop="nickname" />
|
||||
<el-table-column label="产品名称" align="center" prop="productName" />
|
||||
<el-table-column label="设备状态" align="center" prop="state">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="row.state" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<Pagination
|
||||
v-model:page="bindQueryParams.pageNo"
|
||||
v-model:limit="bindQueryParams.pageSize"
|
||||
:total="bindTotal"
|
||||
@pagination="getBindableDevicePage"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="handleBindSubmit" :loading="bindFormLoading">
|
||||
确定(已选 {{ bindSelectedIds.length }} 个)
|
||||
</el-button>
|
||||
<el-button @click="bindDialogVisible = false">取消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DeviceApi, DeviceVO } from '@/api/iot/device/device'
|
||||
import { DeviceTypeEnum } from '@/api/iot/product/product'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import ProductSelect from '@/views/iot/product/product/components/ProductSelect.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
gatewayId: number
|
||||
}>()
|
||||
|
||||
const message = useMessage()
|
||||
const { push } = useRouter()
|
||||
|
||||
const loading = ref(false) // 列表加载状态
|
||||
const subDeviceList = ref<DeviceVO[]>([]) // 子设备列表
|
||||
const selectedIds = ref<number[]>([]) // 选中的设备ID
|
||||
|
||||
const bindDialogVisible = ref(false) // 绑定弹窗可见性
|
||||
const bindFormLoading = ref(false) // 绑定弹窗加载状态
|
||||
const bindTableRef = ref()
|
||||
const bindQueryFormRef = ref()
|
||||
const bindableDevices = ref<DeviceVO[]>([]) // 可绑定设备列表
|
||||
const bindSelectedIds = ref<number[]>([]) // 绑定选中的设备ID
|
||||
const bindTotal = ref(0) // 可绑定设备总数
|
||||
const bindQueryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
productId: undefined as number | undefined,
|
||||
deviceName: ''
|
||||
})
|
||||
|
||||
/** 获取子设备列表 */
|
||||
const getSubDeviceList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
subDeviceList.value = await DeviceApi.getSubDeviceList(props.gatewayId)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 打开设备详情 */
|
||||
const openDeviceDetail = (id: number) => {
|
||||
push({ name: 'IoTDeviceDetail', params: { id } })
|
||||
}
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: DeviceVO[]) => {
|
||||
selectedIds.value = selection.map((item) => item.id)
|
||||
}
|
||||
|
||||
/** 打开绑定弹窗 */
|
||||
const openBindDialog = async () => {
|
||||
bindSelectedIds.value = []
|
||||
bindDialogVisible.value = true
|
||||
await getBindableDevicePage()
|
||||
}
|
||||
|
||||
/** 获取可绑定设备分页 */
|
||||
const getBindableDevicePage = async () => {
|
||||
bindFormLoading.value = true
|
||||
try {
|
||||
const result = await DeviceApi.getUnboundSubDevicePage(bindQueryParams)
|
||||
bindableDevices.value = result.list
|
||||
bindTotal.value = result.total
|
||||
} finally {
|
||||
bindFormLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置绑定弹窗搜索条件 */
|
||||
const resetBindQuery = () => {
|
||||
bindQueryParams.pageNo = 1
|
||||
bindQueryParams.productId = undefined
|
||||
bindQueryParams.deviceName = ''
|
||||
getBindableDevicePage()
|
||||
}
|
||||
|
||||
/** 绑定弹窗多选框选中数据 */
|
||||
const handleBindSelectionChange = (selection: DeviceVO[]) => {
|
||||
bindSelectedIds.value = selection.map((item) => item.id)
|
||||
}
|
||||
|
||||
/** 提交绑定 */
|
||||
const handleBindSubmit = async () => {
|
||||
if (bindSelectedIds.value.length === 0) {
|
||||
message.warning('请选择要绑定的子设备')
|
||||
return
|
||||
}
|
||||
bindFormLoading.value = true
|
||||
try {
|
||||
await DeviceApi.bindDeviceGateway({
|
||||
subIds: bindSelectedIds.value,
|
||||
gatewayId: props.gatewayId
|
||||
})
|
||||
message.success('绑定成功')
|
||||
bindDialogVisible.value = false
|
||||
await getSubDeviceList()
|
||||
} finally {
|
||||
bindFormLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 解绑单个设备 */
|
||||
const handleUnbind = async (id: number) => {
|
||||
try {
|
||||
await message.confirm('确定要解绑该子设备吗?')
|
||||
await DeviceApi.unbindDeviceGateway({ subIds: [id], gatewayId: props.gatewayId })
|
||||
message.success('解绑成功')
|
||||
await getSubDeviceList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 批量解绑 */
|
||||
const handleUnbindBatch = async () => {
|
||||
try {
|
||||
await message.confirm(`确定要解绑选中的 ${selectedIds.value.length} 个子设备吗?`)
|
||||
await DeviceApi.unbindDeviceGateway({ subIds: selectedIds.value, gatewayId: props.gatewayId })
|
||||
message.success('批量解绑成功')
|
||||
selectedIds.value = []
|
||||
await getSubDeviceList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await getSubDeviceList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -17,7 +17,13 @@
|
|||
:thing-model-list="thingModelList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="子设备管理" v-if="product.deviceType === DeviceTypeEnum.GATEWAY" />
|
||||
<el-tab-pane
|
||||
label="子设备管理"
|
||||
name="subDevice"
|
||||
v-if="product.deviceType === DeviceTypeEnum.GATEWAY"
|
||||
>
|
||||
<DeviceDetailsSubDevice v-if="activeTab === 'subDevice'" :gateway-id="device.id" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="设备消息" name="log">
|
||||
<DeviceDetailsMessage v-if="activeTab === 'log'" :device-id="device.id" />
|
||||
</el-tab-pane>
|
||||
|
|
@ -50,6 +56,7 @@ import DeviceDetailsThingModel from './DeviceDetailsThingModel.vue'
|
|||
import DeviceDetailsMessage from './DeviceDetailsMessage.vue'
|
||||
import DeviceDetailsSimulator from './DeviceDetailsSimulator.vue'
|
||||
import DeviceDetailConfig from './DeviceDetailConfig.vue'
|
||||
import DeviceDetailsSubDevice from './DeviceDetailsSubDevice.vue'
|
||||
|
||||
defineOptions({ name: 'IoTDeviceDetail' })
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,20 @@
|
|||
</el-form-item>
|
||||
<el-collapse>
|
||||
<el-collapse-item title="更多配置">
|
||||
<el-form-item label="动态注册" prop="registerEnabled">
|
||||
<template #label>
|
||||
<el-tooltip
|
||||
content="设备动态注册无需一一烧录设备证书(DeviceSecret),每台设备烧录相同的产品证书,即 ProductKey 和 ProductSecret ,云端鉴权通过后下发设备证书,您可以根据需要开启或关闭动态注册,保障安全性。"
|
||||
placement="top"
|
||||
>
|
||||
<span>
|
||||
动态注册
|
||||
<Icon icon="ep:question-filled" class="ml-2px" />
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<el-switch v-model="formData.registerEnabled" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品图标" prop="icon">
|
||||
<UploadImg v-model="formData.icon" :height="'80px'" :width="'80px'" />
|
||||
</el-form-item>
|
||||
|
|
@ -120,7 +134,8 @@ const formData = ref({
|
|||
description: undefined,
|
||||
deviceType: undefined,
|
||||
netType: undefined,
|
||||
codecType: CodecTypeEnum.ALINK
|
||||
codecType: CodecTypeEnum.ALINK,
|
||||
registerEnabled: false
|
||||
})
|
||||
const formRules = reactive({
|
||||
productKey: [{ required: true, message: 'ProductKey 不能为空', trigger: 'blur' }],
|
||||
|
|
@ -194,7 +209,8 @@ const resetForm = () => {
|
|||
description: undefined,
|
||||
deviceType: undefined,
|
||||
netType: undefined,
|
||||
codecType: CodecTypeEnum.ALINK
|
||||
codecType: CodecTypeEnum.ALINK,
|
||||
registerEnabled: false
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
<!-- 产品下拉选择器组件 -->
|
||||
<template>
|
||||
<el-select
|
||||
:model-value="modelValue"
|
||||
@update:model-value="handleChange"
|
||||
placeholder="请选择产品"
|
||||
filterable
|
||||
clearable
|
||||
class="w-full"
|
||||
:loading="loading"
|
||||
>
|
||||
<el-option
|
||||
v-for="product in productList"
|
||||
:key="product.id"
|
||||
:label="product.name"
|
||||
:value="product.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProductApi } from '@/api/iot/product/product'
|
||||
|
||||
/** 产品下拉选择器组件 */
|
||||
defineOptions({ name: 'ProductSelect' })
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue?: number
|
||||
deviceType?: number // 设备类型过滤
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value?: number): void
|
||||
(e: 'change', value?: number): void
|
||||
}>()
|
||||
|
||||
const loading = ref(false) // 产品加载状态
|
||||
const productList = ref<any[]>([]) // 产品列表
|
||||
|
||||
/**
|
||||
* 处理选择变化事件
|
||||
*
|
||||
* @param value 选中的产品 ID
|
||||
*/
|
||||
const handleChange = (value?: number) => {
|
||||
emit('update:modelValue', value)
|
||||
emit('change', value)
|
||||
}
|
||||
|
||||
/** 获取产品列表 */
|
||||
const getProductList = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const res = await ProductApi.getSimpleProductList(props.deviceType)
|
||||
productList.value = res || []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 组件挂载时获取产品列表 */
|
||||
onMounted(() => {
|
||||
getProductList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -21,6 +21,28 @@
|
|||
>
|
||||
<dict-tag :type="DICT_TYPE.IOT_NET_TYPE" :value="product.netType" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="动态注册">
|
||||
<el-tag :type="product.registerEnabled ? 'success' : 'info'">
|
||||
{{ product.registerEnabled ? '已开启' : '已关闭' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="产品密钥">
|
||||
<div class="flex items-center">
|
||||
<span>{{ secretVisible ? product.productSecret : '******' }}</span>
|
||||
<el-button link type="primary" class="ml-2" @click="secretVisible = !secretVisible">
|
||||
<Icon :icon="secretVisible ? 'ep:hide' : 'ep:view'" />
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="secretVisible && product.productSecret"
|
||||
link
|
||||
type="primary"
|
||||
class="ml-1"
|
||||
@click="copySecret"
|
||||
>
|
||||
<Icon icon="ep:document-copy" />
|
||||
</el-button>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="产品描述">{{ product.description }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</ContentWrap>
|
||||
|
|
@ -29,6 +51,19 @@
|
|||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { DeviceTypeEnum, ProductVO } from '@/api/iot/product/product'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
|
||||
const { product } = defineProps<{ product: ProductVO }>()
|
||||
|
||||
const message = useMessage()
|
||||
const secretVisible = ref(false)
|
||||
const { copy } = useClipboard()
|
||||
|
||||
/** 复制产品密钥 */
|
||||
const copySecret = async () => {
|
||||
if (product.productSecret) {
|
||||
await copy(product.productSecret)
|
||||
message.success('复制成功')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,41 @@ export const IotDeviceMessageMethodEnum = {
|
|||
// ========== 设备状态 ==========
|
||||
STATE_UPDATE: {
|
||||
method: 'thing.state.update',
|
||||
name: '设备状态变更',
|
||||
name: '设备状态更新',
|
||||
upstream: true
|
||||
},
|
||||
|
||||
// ========== 拓扑管理 ==========
|
||||
TOPO_ADD: {
|
||||
method: 'thing.topo.add',
|
||||
name: '添加拓扑关系',
|
||||
upstream: true
|
||||
},
|
||||
TOPO_DELETE: {
|
||||
method: 'thing.topo.delete',
|
||||
name: '删除拓扑关系',
|
||||
upstream: true
|
||||
},
|
||||
TOPO_GET: {
|
||||
method: 'thing.topo.get',
|
||||
name: '获取拓扑关系',
|
||||
upstream: true
|
||||
},
|
||||
TOPO_CHANGE: {
|
||||
method: 'thing.topo.change',
|
||||
name: '拓扑关系变更通知',
|
||||
upstream: false
|
||||
},
|
||||
|
||||
// ========== 设备注册 ==========
|
||||
DEVICE_REGISTER: {
|
||||
method: 'thing.auth.register',
|
||||
name: '设备动态注册',
|
||||
upstream: true
|
||||
},
|
||||
SUB_DEVICE_REGISTER: {
|
||||
method: 'thing.auth.register.sub',
|
||||
name: '子设备动态注册',
|
||||
upstream: true
|
||||
},
|
||||
|
||||
|
|
@ -39,6 +73,11 @@ export const IotDeviceMessageMethodEnum = {
|
|||
name: '属性设置',
|
||||
upstream: false
|
||||
},
|
||||
PROPERTY_PACK_POST: {
|
||||
method: 'thing.event.property.pack.post',
|
||||
name: '批量上报(属性 + 事件 + 子设备)',
|
||||
upstream: true
|
||||
},
|
||||
|
||||
// ========== 设备事件 ==========
|
||||
EVENT_POST: {
|
||||
|
|
@ -59,6 +98,18 @@ export const IotDeviceMessageMethodEnum = {
|
|||
method: 'thing.config.push',
|
||||
name: '配置推送',
|
||||
upstream: false
|
||||
},
|
||||
|
||||
// ========== OTA 固件 ==========
|
||||
OTA_UPGRADE: {
|
||||
method: 'thing.ota.upgrade',
|
||||
name: 'OTA 固件信息推送',
|
||||
upstream: false
|
||||
},
|
||||
OTA_PROGRESS: {
|
||||
method: 'thing.ota.progress',
|
||||
name: 'OTA 升级进度上报',
|
||||
upstream: true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue