Showing
25 changed files
with
1193 additions
and
123 deletions
... | ... | @@ -3,6 +3,7 @@ import { |
3 | 3 | TDeviceConfigParams, |
4 | 4 | IDeviceConfigAddOrEditModel, |
5 | 5 | ProfileRecord, |
6 | + RuleChainRecord, | |
6 | 7 | } from '/@/api/device/model/deviceConfigModel'; |
7 | 8 | import { PaginationResult } from '/#/axios'; |
8 | 9 | |
... | ... | @@ -36,7 +37,7 @@ export const deviceConfigGetDetail = (id: string) => { |
36 | 37 | * 获取规则链 |
37 | 38 | */ |
38 | 39 | export const deviceConfigGetRuleChain = () => { |
39 | - return defHttp.get({ | |
40 | + return defHttp.get<RuleChainRecord[]>({ | |
40 | 41 | url: EDeviceConfigApi.DEVICE_CONFIG_GET_RULECHAIN, |
41 | 42 | }); |
42 | 43 | }; | ... | ... |
... | ... | @@ -241,3 +241,21 @@ export interface ProfileRecord { |
241 | 241 | |
242 | 242 | checked?: boolean; |
243 | 243 | } |
244 | + | |
245 | +export interface IDRecord { | |
246 | + entityType: string; | |
247 | + id: string; | |
248 | +} | |
249 | + | |
250 | +export interface RuleChainRecord { | |
251 | + id: IDRecord; | |
252 | + createdTime: number; | |
253 | + additionalInfo?: any; | |
254 | + tenantId: IDRecord; | |
255 | + name: string; | |
256 | + type: string; | |
257 | + firstRuleNodeId: IDRecord; | |
258 | + root: boolean; | |
259 | + debugMode: boolean; | |
260 | + configuration?: any; | |
261 | +} | ... | ... |
... | ... | @@ -54,8 +54,84 @@ export interface Configuration { |
54 | 54 | type: string; |
55 | 55 | } |
56 | 56 | |
57 | +export interface TransportPayloadTypeConfiguration { | |
58 | + transportPayloadType: string; | |
59 | + deviceTelemetryProtoSchema: string; | |
60 | + deviceAttributesProtoSchema: string; | |
61 | + deviceRpcRequestProtoSchema: string; | |
62 | + deviceRpcResponseProtoSchema: string; | |
63 | + enableCompatibilityWithJsonPayloadFormat: boolean; | |
64 | + useJsonPayloadFormatForDefaultDownlinkTopics: boolean; | |
65 | +} | |
66 | + | |
67 | +export interface ClientSettings { | |
68 | + edrxCycle: string; | |
69 | + pagingTransmissionWindow: string; | |
70 | + powerMode: string; | |
71 | + psmActivityTimer: number; | |
72 | + | |
73 | + clientOnlyObserveAfterConnect: string; | |
74 | + fwUpdateResource: string; | |
75 | + fwUpdateStrategy: number; | |
76 | + swUpdateResource: string; | |
77 | + swUpdateStrategy: number; | |
78 | +} | |
79 | + | |
80 | +export interface Bootstrap { | |
81 | + securityMode: string; | |
82 | + shortServerId: number; | |
83 | + bootstrapServerIs: boolean; | |
84 | + host: string; | |
85 | + port: number; | |
86 | + clientHoldOffTime: number; | |
87 | + serverPublicKey?: any; | |
88 | + serverCertificate?: any; | |
89 | + bootstrapServerAccountTimeout: number; | |
90 | + lifetime: number; | |
91 | + defaultMinPeriod: number; | |
92 | + notifIfDisabled: boolean; | |
93 | + binding: string; | |
94 | +} | |
95 | + | |
96 | +export interface Mapping { | |
97 | + dataType: string; | |
98 | + key: string; | |
99 | + oid: string; | |
100 | +} | |
101 | + | |
102 | +export interface CommunicationConfigs { | |
103 | + spec: string; | |
104 | + mappings: Mapping[]; | |
105 | + queryingFrequencyMs: number; | |
106 | +} | |
107 | + | |
57 | 108 | export interface TransportConfiguration { |
58 | 109 | type: string; |
110 | + deviceTelemetryTopic: string; | |
111 | + deviceAttributesTopic: string; | |
112 | + | |
113 | + // MQTT | |
114 | + transportPayloadTypeConfiguration: TransportPayloadTypeConfiguration; | |
115 | + | |
116 | + // COAP | |
117 | + clientSettings: ClientSettings; | |
118 | + coapDeviceTypeConfiguration: { | |
119 | + coapDeviceType: string; | |
120 | + transportPayloadTypeConfiguration: TransportPayloadTypeConfiguration; | |
121 | + }; | |
122 | + | |
123 | + // LWM2M | |
124 | + bootstrapServerUpdateEnable: boolean; | |
125 | + bootstrap: Bootstrap[]; | |
126 | + clientLwM2mSettings: ClientSettings; | |
127 | + | |
128 | + // SNMP | |
129 | + retries: number; | |
130 | + timeoutMs: number; | |
131 | + communicationConfigs: CommunicationConfigs[]; | |
132 | + | |
133 | + // TCP | |
134 | + scriptId: string; | |
59 | 135 | } |
60 | 136 | |
61 | 137 | export interface ProvisionConfiguration { |
... | ... | @@ -85,6 +161,7 @@ export interface DeviceRecord { |
85 | 161 | image: string; |
86 | 162 | type: string; |
87 | 163 | default: boolean; |
164 | + defaultRuleChainId: string; | |
88 | 165 | } |
89 | 166 | |
90 | 167 | export interface DeviceModelOfMatterAttrs { | ... | ... |
1 | +import { ProfileRecord } from '../device/model/deviceConfigModel'; | |
1 | 2 | import { |
2 | 3 | CreateOtaPackageParams, |
3 | 4 | DefaultDeviceProfileInfo, |
... | ... | @@ -129,7 +130,7 @@ export const getDeviceProfileInfos = (params: GetDeviceProfileInfosParams) => { |
129 | 130 | }; |
130 | 131 | |
131 | 132 | export const getDeviceProfileInfoById = (id: string) => { |
132 | - return defHttp.get<DeviceProfileRecord>( | |
133 | + return defHttp.get<ProfileRecord>( | |
133 | 134 | { |
134 | 135 | url: `${Api.GET_DEVICE_PROFILE_INFO_BY_ID}/${id}`, |
135 | 136 | }, | ... | ... |
... | ... | @@ -24,12 +24,11 @@ export interface ScriptRecord { |
24 | 24 | id: string; |
25 | 25 | creator: string; |
26 | 26 | createTime: string; |
27 | - updater: string; | |
28 | - updateTime: string; | |
29 | 27 | name: string; |
30 | - convertJs: string; | |
31 | - enabled: boolean; | |
32 | 28 | tenantId: string; |
33 | 29 | description: string; |
34 | - status: boolean; | |
30 | + convertJs: string; | |
31 | + status: number; | |
32 | + dataType: string; | |
33 | + saveOriginalData: boolean; | |
35 | 34 | } | ... | ... |
src/components/Widget/AuthDropDown.vue
0 → 100644
src/components/Widget/AuthIcon.vue
0 → 100644
... | ... | @@ -8,7 +8,14 @@ |
8 | 8 | centered |
9 | 9 | :canFullscreen="false" |
10 | 10 | > |
11 | - <BasicForm @register="registerForm" /> | |
11 | + <BasicForm @register="registerForm"> | |
12 | + <template #clientId="{ field, model }"> | |
13 | + <div class="flex items-center"> | |
14 | + <Input v-model:value="model[field]" placeholder="请输入客户端ID" /> | |
15 | + <ReloadOutlined class="ml-3 !text-blue-600" @click="handleCreateUUID" /> | |
16 | + </div> | |
17 | + </template> | |
18 | + </BasicForm> | |
12 | 19 | </BasicModal> |
13 | 20 | </template> |
14 | 21 | |
... | ... | @@ -19,10 +26,15 @@ |
19 | 26 | import { TokenSchemas, credentialTypeEnum } from '../../config/data'; |
20 | 27 | import { saveDeviceToken } from '/@/api/device/deviceManager'; |
21 | 28 | import { useMessage } from '/@/hooks/web/useMessage'; |
29 | + import { Input } from 'ant-design-vue'; | |
30 | + import { buildUUID } from '/@/utils/uuid'; | |
31 | + import { ReloadOutlined } from '@ant-design/icons-vue'; | |
22 | 32 | export default defineComponent({ |
23 | 33 | components: { |
24 | 34 | BasicModal, |
25 | 35 | BasicForm, |
36 | + Input, | |
37 | + ReloadOutlined, | |
26 | 38 | }, |
27 | 39 | emits: ['register'], |
28 | 40 | setup() { |
... | ... | @@ -36,7 +48,7 @@ |
36 | 48 | showSubmitButton: false, |
37 | 49 | showResetButton: false, |
38 | 50 | wrapperCol: { |
39 | - span: 12, | |
51 | + span: 16, | |
40 | 52 | }, |
41 | 53 | }); |
42 | 54 | const [registerModal, { closeModal }] = useModalInner(async (data) => { |
... | ... | @@ -208,12 +220,17 @@ |
208 | 220 | }) |
209 | 221 | .catch(() => {}); |
210 | 222 | }; |
223 | + | |
224 | + const handleCreateUUID = () => { | |
225 | + setFieldsValue({ clientId: buildUUID() }); | |
226 | + }; | |
211 | 227 | return { |
212 | 228 | registerModal, |
213 | 229 | registerForm, |
214 | 230 | checkedChange, |
215 | 231 | handleCancel, |
216 | 232 | handleOk, |
233 | + handleCreateUUID, | |
217 | 234 | }; |
218 | 235 | }, |
219 | 236 | }); | ... | ... |
... | ... | @@ -27,6 +27,7 @@ |
27 | 27 | import { useDrawer } from '/@/components/Drawer'; |
28 | 28 | import productDefault from '/@/assets/icons/product-default.svg'; |
29 | 29 | import { usePermission } from '/@/hooks/web/usePermission'; |
30 | + import { useRoute } from 'vue-router'; | |
30 | 31 | |
31 | 32 | defineProps<{ |
32 | 33 | mode: EnumTableCardMode; |
... | ... | @@ -43,7 +44,7 @@ |
43 | 44 | const { createMessage } = useMessage(); |
44 | 45 | const { createSyncConfirm } = useSyncConfirm(); |
45 | 46 | |
46 | - const [register, { getFieldsValue }] = useForm({ | |
47 | + const [register, { getFieldsValue, setFieldsValue }] = useForm({ | |
47 | 48 | showAdvancedButton: true, |
48 | 49 | labelWidth: 100, |
49 | 50 | compact: true, |
... | ... | @@ -83,14 +84,18 @@ |
83 | 84 | .map((item) => item.id); |
84 | 85 | }); |
85 | 86 | |
86 | - const getDataSource = async () => { | |
87 | + const getDataSource = async (otherParams: Recordable = {}) => { | |
87 | 88 | try { |
88 | 89 | loading.value = true; |
90 | + if (otherParams) { | |
91 | + setFieldsValue(otherParams); | |
92 | + } | |
89 | 93 | const params = getFieldsValue(); |
90 | 94 | const { items, total } = await deviceConfigGetQuery({ |
91 | 95 | page: pagination.current, |
92 | 96 | pageSize: unref(colNumber) * 2, |
93 | 97 | ...params, |
98 | + ...otherParams, | |
94 | 99 | }); |
95 | 100 | pagination.total = total; |
96 | 101 | dataSource.value = items.map((item) => ({ ...item, checked: false })); |
... | ... | @@ -192,9 +197,9 @@ |
192 | 197 | throw error; |
193 | 198 | } |
194 | 199 | }; |
195 | - | |
200 | + const { query: routeParams } = useRoute(); | |
196 | 201 | onMounted(() => { |
197 | - getDataSource(); | |
202 | + getDataSource(routeParams); | |
198 | 203 | }); |
199 | 204 | </script> |
200 | 205 | |
... | ... | @@ -255,7 +260,7 @@ |
255 | 260 | <Image |
256 | 261 | @click.stop |
257 | 262 | :height="144" |
258 | - :src="item.image" | |
263 | + :src="item.image || IMAGE_FALLBACK" | |
259 | 264 | placeholder |
260 | 265 | :fallback="IMAGE_FALLBACK" |
261 | 266 | /> | ... | ... |
... | ... | @@ -3,14 +3,13 @@ |
3 | 3 | <Tabs v-model:activeKey="activeKey" @change="handlePanelChange"> |
4 | 4 | <Tabs.TabPane key="product" tab="产品"> |
5 | 5 | <div class="relative"> |
6 | - <DeviceConfigurationStep :ifShowBtn="false" ref="DevConStRef" /> | |
7 | - <div class="absolute w-full h-full top-0 cursor-not-allowed"></div> | |
6 | + <ProductDescription ref="DevConStRef" :record="record" /> | |
8 | 7 | </div> |
9 | 8 | </Tabs.TabPane> |
10 | 9 | <Tabs.TabPane key="transport" tab="传输配置"> |
11 | - <div class="relative"> | |
12 | - <TransportConfigurationStep :ifShowBtn="false" ref="TransConStRef" /> | |
13 | - <div class="absolute w-full h-full top-0 cursor-not-allowed"></div> | |
10 | + <div> | |
11 | + <TransportDescription :record="record" /> | |
12 | + <!-- <TransportConfigurationStep :ifShowBtn="false" ref="TransConStRef" /> --> | |
14 | 13 | </div> |
15 | 14 | </Tabs.TabPane> |
16 | 15 | <Tabs.TabPane key="topic" tab="Topic"> |
... | ... | @@ -25,13 +24,14 @@ |
25 | 24 | <script lang="ts" setup> |
26 | 25 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
27 | 26 | import { Tabs } from 'ant-design-vue'; |
28 | - import DeviceConfigurationStep from './step/DeviceConfigurationStep.vue'; | |
29 | 27 | import TransportConfigurationStep from './step/TransportConfigurationStep.vue'; |
30 | 28 | import PhysicalModelManagementStep from './step/PhysicalModelManagementStep.vue'; |
31 | 29 | import { nextTick, ref, unref } from 'vue'; |
32 | 30 | import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi'; |
33 | 31 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
34 | 32 | import TopicPanel from './step/TopicPanel.vue'; |
33 | + import ProductDescription from './components/ProductDescription.vue'; | |
34 | + import { TransportDescription } from './components/TransportDescript'; | |
35 | 35 | |
36 | 36 | defineEmits(['register']); |
37 | 37 | |
... | ... | @@ -41,12 +41,11 @@ |
41 | 41 | |
42 | 42 | const record = ref<DeviceRecord>({} as unknown as DeviceRecord); |
43 | 43 | |
44 | - const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>(); | |
44 | + const DevConStRef = ref<InstanceType<typeof ProductDescription>>(); | |
45 | 45 | const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>(); |
46 | - // const PhysicalModManRef = ref<InstanceType<typeof PhysicalModelManagementStep>>(); | |
47 | 46 | |
48 | - const setDeviceConfFormData = async (res: Recordable) => { | |
49 | - unref(DevConStRef)?.setFormData(res); | |
47 | + const setDeviceConfFormData = async () => { | |
48 | + unref(DevConStRef)?.renderProductInfo(); | |
50 | 49 | }; |
51 | 50 | const setTransConfFormData = async (res: Recordable) => { |
52 | 51 | await nextTick(); |
... | ... | @@ -57,7 +56,7 @@ |
57 | 56 | activeKey.value = 'product'; |
58 | 57 | record.value = data.record; |
59 | 58 | record.value = await deviceConfigGetDetail(data.record.id); |
60 | - setDeviceConfFormData(unref(record)); | |
59 | + setDeviceConfFormData(); | |
61 | 60 | }); |
62 | 61 | |
63 | 62 | const handlePanelChange = (activeKey: ActiveKey) => { | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { Spin, Image } from 'ant-design-vue'; | |
3 | + import { ref, unref, h } from 'vue'; | |
4 | + import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi'; | |
5 | + import { RuleChainRecord } from '/@/api/device/model/deviceConfigModel'; | |
6 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
7 | + import { findDictItemByCode } from '/@/api/system/dict'; | |
8 | + import { SysDictItemResult } from '/@/api/system/model/dictModel'; | |
9 | + import { Description, useDescription } from '/@/components/Description'; | |
10 | + import { to } from '/@/utils/to'; | |
11 | + import productDefaultImage from '/@/assets/icons/product-default.svg'; | |
12 | + | |
13 | + const loading = ref(false); | |
14 | + | |
15 | + const props = defineProps<{ | |
16 | + record: DeviceRecord; | |
17 | + }>(); | |
18 | + | |
19 | + const data = ref<DeviceRecord>({} as unknown as DeviceRecord); | |
20 | + | |
21 | + const [register, { setDescProps }] = useDescription({ | |
22 | + layout: 'vertical', | |
23 | + column: 2, | |
24 | + schema: [ | |
25 | + { | |
26 | + field: 'image', | |
27 | + label: '图片', | |
28 | + span: 2, | |
29 | + render: (val) => { | |
30 | + return h(Image, { src: val || productDefaultImage, height: 200 }); | |
31 | + }, | |
32 | + }, | |
33 | + { | |
34 | + field: 'deviceType', | |
35 | + label: '设备类型', | |
36 | + }, | |
37 | + { | |
38 | + field: 'name', | |
39 | + label: '产品名称', | |
40 | + }, | |
41 | + { | |
42 | + field: 'ruleChain', | |
43 | + label: '规则链', | |
44 | + }, | |
45 | + { | |
46 | + field: 'queueName', | |
47 | + label: '处理队列', | |
48 | + }, | |
49 | + { | |
50 | + field: 'description', | |
51 | + label: '描述', | |
52 | + render(val) { | |
53 | + return h('div', { class: 'min-h-6' }, val); | |
54 | + }, | |
55 | + }, | |
56 | + ], | |
57 | + }); | |
58 | + | |
59 | + const findDeviceType = async (deviceType: string) => { | |
60 | + const [error, data] = await to<SysDictItemResult[]>( | |
61 | + findDictItemByCode({ dictCode: 'device_type' }) | |
62 | + ); | |
63 | + if (!error) { | |
64 | + const record = data.find((item) => item.itemValue === deviceType); | |
65 | + return { deviceType: record?.itemText }; | |
66 | + } | |
67 | + return {}; | |
68 | + }; | |
69 | + | |
70 | + const findHandleQueue = async (defaultQueueName: string) => { | |
71 | + const [error, data] = await to<SysDictItemResult[]>( | |
72 | + findDictItemByCode({ dictCode: 'queen_execute_sequence' }) | |
73 | + ); | |
74 | + if (!error) { | |
75 | + const record = data.find((item) => item.itemValue === defaultQueueName); | |
76 | + return { queueName: record?.itemText }; | |
77 | + } | |
78 | + return {}; | |
79 | + }; | |
80 | + | |
81 | + const findRuleChain = async (ruleChain: string) => { | |
82 | + const [error, data] = await to<RuleChainRecord[]>(deviceConfigGetRuleChain()); | |
83 | + if (!error) { | |
84 | + const record = data.find((item) => item.id.id === ruleChain); | |
85 | + return { ruleChain: record?.name }; | |
86 | + } | |
87 | + return {}; | |
88 | + }; | |
89 | + | |
90 | + const renderProductInfo = async () => { | |
91 | + try { | |
92 | + data.value = {} as unknown as DeviceRecord; | |
93 | + loading.value = true; | |
94 | + const { defaultRuleChainId, deviceType, defaultQueueName } = props.record; | |
95 | + data.value = props.record; | |
96 | + const values = await Promise.all([ | |
97 | + findDeviceType(deviceType), | |
98 | + findHandleQueue(defaultQueueName), | |
99 | + findRuleChain(defaultRuleChainId), | |
100 | + ]); | |
101 | + const value = values.reduce((prev, next) => ({ ...prev, ...next }), {}); | |
102 | + data.value = Object.assign(unref(data), value); | |
103 | + setDescProps({ data: unref(data) }); | |
104 | + } catch (error) { | |
105 | + throw error; | |
106 | + } finally { | |
107 | + loading.value = false; | |
108 | + } | |
109 | + }; | |
110 | + | |
111 | + defineExpose({ | |
112 | + renderProductInfo, | |
113 | + }); | |
114 | +</script> | |
115 | + | |
116 | +<template> | |
117 | + <Spin :spinning="loading"> | |
118 | + <Description class="product-description" @register="register" /> | |
119 | + </Spin> | |
120 | +</template> | |
121 | + | |
122 | +<style lang="less" scoped> | |
123 | + .product-description:deep(.ant-image-img) { | |
124 | + height: 200px !important; | |
125 | + } | |
126 | +</style> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
3 | + import { useDescription, Description } from '/@/components/Description'; | |
4 | + import { Input } from 'ant-design-vue'; | |
5 | + import { h } from 'vue'; | |
6 | + import { | |
7 | + COAPDeviceTypeEnum, | |
8 | + PowerModeEnum, | |
9 | + PowerModeNameEnum, | |
10 | + TransportPayloadTypeEnum, | |
11 | + } from './const'; | |
12 | + | |
13 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
14 | + const props = defineProps<{ | |
15 | + record: TransportConfiguration; | |
16 | + }>(); | |
17 | + | |
18 | + const showProtoSchema = (data: TransportConfiguration) => { | |
19 | + return ( | |
20 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.transportPayloadType === | |
21 | + TransportPayloadTypeEnum.PROTOBUF && | |
22 | + data.coapDeviceTypeConfiguration.coapDeviceType === COAPDeviceTypeEnum.DEFAULT | |
23 | + ); | |
24 | + }; | |
25 | + | |
26 | + const showPowerModeIsPSM = (data: TransportConfiguration) => { | |
27 | + return data.clientSettings.powerMode === PowerModeNameEnum.PSM; | |
28 | + }; | |
29 | + | |
30 | + const showPowerModeIsEDRX = (data: TransportConfiguration) => { | |
31 | + return data.clientSettings.powerMode === PowerModeEnum.E_DRX; | |
32 | + }; | |
33 | + | |
34 | + const [register] = useDescription({ | |
35 | + layout: 'vertical', | |
36 | + column: 2, | |
37 | + data: props.record, | |
38 | + schema: [ | |
39 | + { | |
40 | + field: 'type', | |
41 | + label: '接入协议', | |
42 | + }, | |
43 | + { | |
44 | + field: 'coapDeviceType', | |
45 | + label: 'COAP设备类型', | |
46 | + render: (_, data: TransportConfiguration) => | |
47 | + data.coapDeviceTypeConfiguration.coapDeviceType, | |
48 | + }, | |
49 | + { | |
50 | + field: 'coapDeviceType', | |
51 | + label: 'COAP设备消息Payload', | |
52 | + render: (_, data: TransportConfiguration) => | |
53 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.transportPayloadType, | |
54 | + }, | |
55 | + { | |
56 | + field: 'powerMode', | |
57 | + label: '节能模式', | |
58 | + render: (_, data: TransportConfiguration) => | |
59 | + PowerModeNameEnum[data.clientSettings.powerMode], | |
60 | + }, | |
61 | + { | |
62 | + field: 'psmActivityTimer', | |
63 | + label: 'PSM活动计时器', | |
64 | + show: showPowerModeIsPSM, | |
65 | + render: (_, data: TransportConfiguration) => data.clientSettings.psmActivityTimer, | |
66 | + }, | |
67 | + { | |
68 | + field: 'edrxCycle', | |
69 | + label: 'eDRX循环', | |
70 | + show: showPowerModeIsEDRX, | |
71 | + render: (_, data: TransportConfiguration) => data.clientSettings.edrxCycle, | |
72 | + }, | |
73 | + { | |
74 | + field: 'edrxCycleTime', | |
75 | + label: 'eDRX循环时间单位', | |
76 | + show: showPowerModeIsEDRX, | |
77 | + render: () => '秒', | |
78 | + }, | |
79 | + { | |
80 | + field: 'pagingTransmissionWindow', | |
81 | + label: '寻呼传输窗口', | |
82 | + show: showPowerModeIsEDRX, | |
83 | + render: (_, data: TransportConfiguration) => data.clientSettings.pagingTransmissionWindow, | |
84 | + }, | |
85 | + { | |
86 | + field: 'pagingTransmissionWindowTime', | |
87 | + label: '寻呼传输窗口时间单位', | |
88 | + show: showPowerModeIsEDRX, | |
89 | + render: () => '秒', | |
90 | + }, | |
91 | + { | |
92 | + field: 'unit', | |
93 | + label: '时间单位', | |
94 | + show: showPowerModeIsPSM, | |
95 | + render: () => '秒', | |
96 | + }, | |
97 | + { | |
98 | + field: 'deviceTelemetryProtoSchema', | |
99 | + label: '遥测数据 proto schema', | |
100 | + span: 2, | |
101 | + show: showProtoSchema, | |
102 | + render(_, data: TransportConfiguration) { | |
103 | + return h(Input.TextArea, { | |
104 | + autoSize: true, | |
105 | + value: | |
106 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
107 | + .deviceTelemetryProtoSchema, | |
108 | + }); | |
109 | + }, | |
110 | + }, | |
111 | + { | |
112 | + field: 'deviceAttributesProtoSchema', | |
113 | + label: 'Attributes proto schema', | |
114 | + span: 2, | |
115 | + show: showProtoSchema, | |
116 | + render(_, data: TransportConfiguration) { | |
117 | + return h(Input.TextArea, { | |
118 | + autoSize: true, | |
119 | + value: | |
120 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
121 | + .deviceAttributesProtoSchema, | |
122 | + }); | |
123 | + }, | |
124 | + }, | |
125 | + { | |
126 | + field: 'deviceRpcRequestProtoSchema', | |
127 | + label: 'RPC 请求 proto schema', | |
128 | + span: 2, | |
129 | + show: showProtoSchema, | |
130 | + render(_, data: TransportConfiguration) { | |
131 | + return h(Input.TextArea, { | |
132 | + autoSize: true, | |
133 | + value: | |
134 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
135 | + .deviceRpcRequestProtoSchema, | |
136 | + }); | |
137 | + }, | |
138 | + }, | |
139 | + { | |
140 | + field: 'deviceRpcResponseProtoSchema', | |
141 | + label: 'RPC 响应 proto schema', | |
142 | + span: 2, | |
143 | + show: showProtoSchema, | |
144 | + render(_, data: TransportConfiguration) { | |
145 | + return h(Input.TextArea, { | |
146 | + autoSize: true, | |
147 | + value: | |
148 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
149 | + .deviceRpcResponseProtoSchema, | |
150 | + }); | |
151 | + }, | |
152 | + }, | |
153 | + ], | |
154 | + }); | |
155 | +</script> | |
156 | + | |
157 | +<template> | |
158 | + <Description @register="register" /> | |
159 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
3 | + import { useDescription, Description } from '/@/components/Description'; | |
4 | + | |
5 | + const props = defineProps<{ | |
6 | + record: DeviceRecord['profileData']['transportConfiguration']; | |
7 | + }>(); | |
8 | + | |
9 | + const [register] = useDescription({ | |
10 | + layout: 'vertical', | |
11 | + column: 2, | |
12 | + schema: [ | |
13 | + { | |
14 | + field: 'type', | |
15 | + label: '接入协议', | |
16 | + }, | |
17 | + ], | |
18 | + data: props.record, | |
19 | + }); | |
20 | +</script> | |
21 | + | |
22 | +<template> | |
23 | + <Description @register="register" /> | |
24 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { Input, Tabs } from 'ant-design-vue'; | |
3 | + import { computed, h, unref } from 'vue'; | |
4 | + import { | |
5 | + BindingNameEnum, | |
6 | + FirmwareUpdateStrategyNameEnum, | |
7 | + PowerModeNameEnum, | |
8 | + SecurityModeNameEnum, | |
9 | + } from './const'; | |
10 | + import { Bootstrap, ClientSettings, DeviceRecord } from '/@/api/device/model/deviceModel'; | |
11 | + import { CollapseContainer } from '/@/components/Container'; | |
12 | + import { useDescription, Description, DescItem } from '/@/components/Description'; | |
13 | + | |
14 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
15 | + const props = defineProps<{ | |
16 | + record: TransportConfiguration; | |
17 | + }>(); | |
18 | + | |
19 | + enum TabKeyEnum { | |
20 | + LWM2M_MODEL = 'LWM2M Model', | |
21 | + BOOTSTRAP = 'Bootstrap', | |
22 | + OTHER_SETTINGS = 'Other settings', | |
23 | + JSON_CONFIG_PROFILE_DEVICE = 'JSON Config Profile Device', | |
24 | + } | |
25 | + | |
26 | + const getBootstrapSetting = computed(() => { | |
27 | + const { record } = props; | |
28 | + return record.bootstrap; | |
29 | + }); | |
30 | + | |
31 | + const getOtherSetting = computed(() => { | |
32 | + const { record } = props; | |
33 | + return record.clientLwM2mSettings; | |
34 | + }); | |
35 | + | |
36 | + const [registerLWM2MModel] = useDescription({ | |
37 | + layout: 'vertical', | |
38 | + column: 2, | |
39 | + data: {}, | |
40 | + schema: [ | |
41 | + { | |
42 | + field: 'objectList', | |
43 | + label: '对象列表', | |
44 | + render: () => h('div', { class: 'min-h-6' }), | |
45 | + }, | |
46 | + ], | |
47 | + }); | |
48 | + | |
49 | + const getCollapseTitle = (item: Bootstrap) => { | |
50 | + return `LwM2M Server Short server ID: ${item.shortServerId} Security config mode: ${item.securityMode}`; | |
51 | + }; | |
52 | + | |
53 | + const bootstrapDescriptionSchema: DescItem[] = [ | |
54 | + { | |
55 | + label: '安全配置', | |
56 | + field: 'securityMode', | |
57 | + render: (_, data: Bootstrap) => SecurityModeNameEnum[data.securityMode], | |
58 | + }, | |
59 | + { | |
60 | + label: '短服务器ID', | |
61 | + field: 'shortServerId', | |
62 | + }, | |
63 | + { | |
64 | + label: '主机', | |
65 | + field: 'host', | |
66 | + }, | |
67 | + { | |
68 | + label: '端口', | |
69 | + field: 'port', | |
70 | + }, | |
71 | + { | |
72 | + label: '延迟时间', | |
73 | + field: 'clientHoldOffTime', | |
74 | + }, | |
75 | + { | |
76 | + label: '超时后的账户', | |
77 | + field: 'bootstrapServerAccountTimeout', | |
78 | + }, | |
79 | + { | |
80 | + label: '注册生存期', | |
81 | + field: 'lifetime', | |
82 | + }, | |
83 | + { | |
84 | + label: '两次通知之间的最小周期', | |
85 | + field: 'defaultMinPeriod', | |
86 | + }, | |
87 | + { | |
88 | + label: 'Binding', | |
89 | + field: 'binding', | |
90 | + span: 2, | |
91 | + render: (_, data: Bootstrap) => BindingNameEnum[data.binding], | |
92 | + }, | |
93 | + { | |
94 | + label: '禁用或脱机时的通知存储', | |
95 | + field: 'notifIfDisabled', | |
96 | + render: (_, data: Bootstrap) => (data.notifIfDisabled ? '启用' : '禁用'), | |
97 | + }, | |
98 | + ]; | |
99 | + console.log(unref(getOtherSetting)); | |
100 | + const [registerOtherSettings] = useDescription({ | |
101 | + layout: 'vertical', | |
102 | + column: 2, | |
103 | + data: unref(getOtherSetting), | |
104 | + schema: [ | |
105 | + { | |
106 | + label: '固件更新策略', | |
107 | + field: 'fwUpdateStrategy', | |
108 | + span: 2, | |
109 | + render: (_, data: ClientSettings) => FirmwareUpdateStrategyNameEnum[data.fwUpdateStrategy], | |
110 | + }, | |
111 | + { | |
112 | + label: '固件更新COAP资源', | |
113 | + field: 'fwUpdateResource', | |
114 | + span: 2, | |
115 | + }, | |
116 | + { | |
117 | + label: '软件更新策略', | |
118 | + field: 'swUpdateStrategy', | |
119 | + span: 2, | |
120 | + render: (_, data: ClientSettings) => FirmwareUpdateStrategyNameEnum[data.swUpdateStrategy], | |
121 | + }, | |
122 | + { | |
123 | + label: '软件更新COAP资源', | |
124 | + field: 'swUpdateResource', | |
125 | + span: 2, | |
126 | + }, | |
127 | + { | |
128 | + label: '节能模式', | |
129 | + field: 'powerMode', | |
130 | + render: (_, data: ClientSettings) => PowerModeNameEnum[data.powerMode], | |
131 | + }, | |
132 | + { | |
133 | + label: 'PSM活动计时器', | |
134 | + field: 'edrxCycle', | |
135 | + }, | |
136 | + { | |
137 | + label: 'PSM活动计时器单位', | |
138 | + field: 'edrxCycleTimeUnit', | |
139 | + render: () => '秒', | |
140 | + }, | |
141 | + { | |
142 | + label: '支持复合读/写观察操作', | |
143 | + field: '', | |
144 | + render: () => '禁用', | |
145 | + }, | |
146 | + ], | |
147 | + }); | |
148 | + | |
149 | + const [registerJSONConfig] = useDescription({ | |
150 | + layout: 'vertical', | |
151 | + column: 2, | |
152 | + data: props.record, | |
153 | + schema: [ | |
154 | + { | |
155 | + field: 'json', | |
156 | + label: 'LWM2M', | |
157 | + render: (_, data: TransportConfiguration) => { | |
158 | + return h(Input.TextArea, { value: JSON.stringify(data, null, 2), autoSize: true }); | |
159 | + }, | |
160 | + }, | |
161 | + ], | |
162 | + }); | |
163 | +</script> | |
164 | + | |
165 | +<template> | |
166 | + <Tabs> | |
167 | + <Tabs.TabPane :tab="TabKeyEnum.LWM2M_MODEL" :key="TabKeyEnum.LWM2M_MODEL"> | |
168 | + <Description @register="registerLWM2MModel" /> | |
169 | + </Tabs.TabPane> | |
170 | + <Tabs.TabPane :tab="TabKeyEnum.BOOTSTRAP" :key="TabKeyEnum.BOOTSTRAP"> | |
171 | + <CollapseContainer | |
172 | + v-for="(item, index) in getBootstrapSetting" | |
173 | + :key="index" | |
174 | + :title="getCollapseTitle(item)" | |
175 | + class="mt-4" | |
176 | + > | |
177 | + <Description | |
178 | + layout="vertical" | |
179 | + :column="2" | |
180 | + :schema="bootstrapDescriptionSchema" | |
181 | + :data="item" | |
182 | + /> | |
183 | + </CollapseContainer> | |
184 | + </Tabs.TabPane> | |
185 | + <Tabs.TabPane :tab="TabKeyEnum.OTHER_SETTINGS" :key="TabKeyEnum.OTHER_SETTINGS"> | |
186 | + <Description @register="registerOtherSettings" /> | |
187 | + </Tabs.TabPane> | |
188 | + <Tabs.TabPane | |
189 | + :tab="TabKeyEnum.JSON_CONFIG_PROFILE_DEVICE" | |
190 | + :key="TabKeyEnum.JSON_CONFIG_PROFILE_DEVICE" | |
191 | + > | |
192 | + <Description @register="registerJSONConfig" /> | |
193 | + </Tabs.TabPane> | |
194 | + </Tabs> | |
195 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
3 | + import { useDescription, Description } from '/@/components/Description'; | |
4 | + import { Input } from 'ant-design-vue'; | |
5 | + import { h } from 'vue'; | |
6 | + import { TransportPayloadTypeEnum } from './const'; | |
7 | + | |
8 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
9 | + const props = defineProps<{ | |
10 | + record: TransportConfiguration; | |
11 | + }>(); | |
12 | + | |
13 | + const [register] = useDescription({ | |
14 | + layout: 'vertical', | |
15 | + column: 2, | |
16 | + data: props.record, | |
17 | + schema: [ | |
18 | + { | |
19 | + field: 'type', | |
20 | + label: '接入协议', | |
21 | + span: 2, | |
22 | + }, | |
23 | + { | |
24 | + field: 'deviceTelemetryTopic', | |
25 | + label: '遥测数据主题筛选器', | |
26 | + }, | |
27 | + { | |
28 | + field: 'deviceAttributesTopic', | |
29 | + label: '属性主题过滤器', | |
30 | + }, | |
31 | + { | |
32 | + field: 'transportPayloadType', | |
33 | + label: 'MQTT设备Payload', | |
34 | + render(_, data: TransportConfiguration) { | |
35 | + return data.transportPayloadTypeConfiguration.transportPayloadType; | |
36 | + }, | |
37 | + }, | |
38 | + { | |
39 | + field: 'enableCompatibilityWithJsonPayloadFormat', | |
40 | + label: '启用与其他有效负载格式的兼容性', | |
41 | + render(_, data: TransportConfiguration) { | |
42 | + return data.transportPayloadTypeConfiguration.enableCompatibilityWithJsonPayloadFormat | |
43 | + ? '启用' | |
44 | + : '关闭'; | |
45 | + }, | |
46 | + }, | |
47 | + { | |
48 | + field: 'deviceTelemetryProtoSchema', | |
49 | + label: '遥测数据 proto schema', | |
50 | + span: 2, | |
51 | + show: (data: TransportConfiguration) => | |
52 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
53 | + TransportPayloadTypeEnum.PROTOBUF, | |
54 | + render(_, data: TransportConfiguration) { | |
55 | + return h(Input.TextArea, { | |
56 | + autoSize: true, | |
57 | + value: data.transportPayloadTypeConfiguration.deviceTelemetryProtoSchema, | |
58 | + }); | |
59 | + }, | |
60 | + }, | |
61 | + { | |
62 | + field: 'deviceAttributesProtoSchema', | |
63 | + label: 'Attributes proto schema', | |
64 | + span: 2, | |
65 | + show: (data: TransportConfiguration) => | |
66 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
67 | + TransportPayloadTypeEnum.PROTOBUF, | |
68 | + render(_, data: TransportConfiguration) { | |
69 | + return h(Input.TextArea, { | |
70 | + autoSize: true, | |
71 | + value: data.transportPayloadTypeConfiguration.deviceAttributesProtoSchema, | |
72 | + }); | |
73 | + }, | |
74 | + }, | |
75 | + { | |
76 | + field: 'deviceRpcRequestProtoSchema', | |
77 | + label: 'RPC 请求 proto schema', | |
78 | + span: 2, | |
79 | + show: (data: TransportConfiguration) => | |
80 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
81 | + TransportPayloadTypeEnum.PROTOBUF, | |
82 | + render(_, data: TransportConfiguration) { | |
83 | + return h(Input.TextArea, { | |
84 | + autoSize: true, | |
85 | + value: data.transportPayloadTypeConfiguration.deviceRpcRequestProtoSchema, | |
86 | + }); | |
87 | + }, | |
88 | + }, | |
89 | + { | |
90 | + field: 'deviceRpcResponseProtoSchema', | |
91 | + label: 'RPC 响应 proto schema', | |
92 | + span: 2, | |
93 | + show: (data: TransportConfiguration) => | |
94 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
95 | + TransportPayloadTypeEnum.PROTOBUF, | |
96 | + render(_, data: TransportConfiguration) { | |
97 | + return h(Input.TextArea, { | |
98 | + autoSize: true, | |
99 | + value: data.transportPayloadTypeConfiguration.deviceRpcResponseProtoSchema, | |
100 | + }); | |
101 | + }, | |
102 | + }, | |
103 | + ], | |
104 | + }); | |
105 | +</script> | |
106 | + | |
107 | +<template> | |
108 | + <Description @register="register" /> | |
109 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { Table } from 'ant-design-vue'; | |
3 | + import { computed, h } from 'vue'; | |
4 | + import { SNMPDataTypeEnum, SNMPRangeNameEnum } from './const'; | |
5 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
6 | + import { CollapseContainer } from '/@/components/Container'; | |
7 | + import { DescItem, Description, useDescription } from '/@/components/Description'; | |
8 | + | |
9 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
10 | + | |
11 | + const props = defineProps<{ | |
12 | + record: TransportConfiguration; | |
13 | + }>(); | |
14 | + | |
15 | + const getSNMPList = computed(() => { | |
16 | + const { record } = props; | |
17 | + return record.communicationConfigs; | |
18 | + }); | |
19 | + | |
20 | + const [register] = useDescription({ | |
21 | + layout: 'vertical', | |
22 | + column: 2, | |
23 | + data: props.record, | |
24 | + schema: [ | |
25 | + { | |
26 | + label: '接入协议', | |
27 | + field: 'type', | |
28 | + span: 2, | |
29 | + }, | |
30 | + { | |
31 | + label: '超时毫秒', | |
32 | + field: 'timeoutMs', | |
33 | + }, | |
34 | + { | |
35 | + label: '重试次数', | |
36 | + field: 'retries', | |
37 | + }, | |
38 | + ], | |
39 | + }); | |
40 | + | |
41 | + const schema: DescItem[] = [ | |
42 | + { | |
43 | + label: '范围', | |
44 | + field: 'spec', | |
45 | + render: (val: string) => getTitle(val), | |
46 | + }, | |
47 | + { | |
48 | + label: '查询频率(毫秒)', | |
49 | + field: 'queryingFrequencyMs', | |
50 | + }, | |
51 | + { | |
52 | + label: 'Mapping', | |
53 | + field: 'mappings', | |
54 | + render: (val) => { | |
55 | + return h(Table, { | |
56 | + size: 'small', | |
57 | + bordered: true, | |
58 | + pagination: false, | |
59 | + columns: [ | |
60 | + { | |
61 | + title: '数据类型', | |
62 | + dataIndex: 'dataType', | |
63 | + customRender: ({ text }) => SNMPDataTypeEnum[text], | |
64 | + }, | |
65 | + { | |
66 | + title: 'DataKey', | |
67 | + dataIndex: 'key', | |
68 | + }, | |
69 | + { | |
70 | + title: 'OID', | |
71 | + dataIndex: 'oid', | |
72 | + }, | |
73 | + ], | |
74 | + dataSource: val, | |
75 | + }); | |
76 | + }, | |
77 | + }, | |
78 | + ]; | |
79 | + | |
80 | + const getTitle = (range: string) => { | |
81 | + return SNMPRangeNameEnum[range]; | |
82 | + }; | |
83 | +</script> | |
84 | + | |
85 | +<template> | |
86 | + <Description @register="register" /> | |
87 | + <CollapseContainer | |
88 | + v-for="(item, index) in getSNMPList" | |
89 | + :key="index" | |
90 | + class="mt-4" | |
91 | + :title="getTitle(item.spec)" | |
92 | + > | |
93 | + <Description :data="item" layout="vertical" :column="2" :schema="schema" /> | |
94 | + </CollapseContainer> | |
95 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { Button, Tag } from 'ant-design-vue'; | |
3 | + import { h, onMounted, ref, unref } from 'vue'; | |
4 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
5 | + import { ScriptRecord } from '/@/api/scriptmanage/model/scriptModel'; | |
6 | + import { getScriptManageMeList } from '/@/api/scriptmanage/scriptManager'; | |
7 | + import { Description, useDescription } from '/@/components/Description'; | |
8 | + import { useModal } from '/@/components/Modal'; | |
9 | + import CoverScriptModal from '/@/views/scriptmanage/converscript/ConverScriptModal.vue'; | |
10 | + | |
11 | + const props = defineProps<{ | |
12 | + record: DeviceRecord['profileData']['transportConfiguration']; | |
13 | + }>(); | |
14 | + | |
15 | + const scriptInfo = ref<ScriptRecord>({} as unknown as ScriptRecord); | |
16 | + | |
17 | + const [register, { setDescProps }] = useDescription({ | |
18 | + layout: 'vertical', | |
19 | + column: 2, | |
20 | + data: props.record, | |
21 | + schema: [ | |
22 | + { | |
23 | + field: 'type', | |
24 | + label: '接入协议', | |
25 | + span: 2, | |
26 | + }, | |
27 | + { | |
28 | + field: 'scriptName', | |
29 | + label: '转换脚本', | |
30 | + render: (value: string) => { | |
31 | + return h('div', [ | |
32 | + h(Tag, { color: 'blue' }, () => value), | |
33 | + h(Button, { type: 'link', onClick: handleTestScript }, () => '测试脚本'), | |
34 | + ]); | |
35 | + }, | |
36 | + }, | |
37 | + ], | |
38 | + }); | |
39 | + | |
40 | + const [registerModal, { openModal }] = useModal(); | |
41 | + | |
42 | + const handleTestScript = () => { | |
43 | + openModal(true, { | |
44 | + isUpdate: false, | |
45 | + isTest: true, | |
46 | + record: unref(scriptInfo).id, | |
47 | + isText: 'test', | |
48 | + isTitle: 'test', | |
49 | + }); | |
50 | + }; | |
51 | + | |
52 | + onMounted(() => { | |
53 | + getTransforScriptInfo(); | |
54 | + }); | |
55 | + | |
56 | + const getTransforScriptInfo = async () => { | |
57 | + try { | |
58 | + const list = await getScriptManageMeList(); | |
59 | + const record = list.find((item) => item.id === props.record.scriptId); | |
60 | + scriptInfo.value = record!; | |
61 | + setDescProps({ | |
62 | + data: Object.assign(props.record, record, { scriptName: record?.name || '' }), | |
63 | + }); | |
64 | + } catch (error) {} | |
65 | + }; | |
66 | +</script> | |
67 | + | |
68 | +<template> | |
69 | + <section> | |
70 | + <Description @register="register" /> | |
71 | + <CoverScriptModal @register="registerModal" /> | |
72 | + </section> | |
73 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { computed } from 'vue'; | |
3 | + import COAPDescription from './COAPDescription.vue'; | |
4 | + import { TransportTypeEnum } from './const'; | |
5 | + import DefaultConfiguration from './DefaultConfiguration.vue'; | |
6 | + import LWM2MDescription from './LWM2MDescription.vue'; | |
7 | + import MQTTConfiguration from './MQTTConfiguration.vue'; | |
8 | + import SNMPDescription from './SNMPDescription.vue'; | |
9 | + import TCPDescription from './TCPDescription.vue'; | |
10 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
11 | + | |
12 | + const props = defineProps<{ | |
13 | + record: DeviceRecord; | |
14 | + }>(); | |
15 | + | |
16 | + const getTransportInfo = computed(() => { | |
17 | + const { record } = props; | |
18 | + return record.profileData.transportConfiguration; | |
19 | + }); | |
20 | +</script> | |
21 | + | |
22 | +<template> | |
23 | + <section> | |
24 | + <DefaultConfiguration | |
25 | + :record="getTransportInfo" | |
26 | + v-if="getTransportInfo.type === TransportTypeEnum.DEFAULT" | |
27 | + /> | |
28 | + | |
29 | + <MQTTConfiguration | |
30 | + :record="getTransportInfo" | |
31 | + v-if="getTransportInfo.type === TransportTypeEnum.MQTT" | |
32 | + /> | |
33 | + | |
34 | + <COAPDescription | |
35 | + :record="getTransportInfo" | |
36 | + v-if="getTransportInfo.type === TransportTypeEnum.COAP" | |
37 | + /> | |
38 | + | |
39 | + <LWM2MDescription | |
40 | + :record="getTransportInfo" | |
41 | + v-if="getTransportInfo.type === TransportTypeEnum.LWM2M" | |
42 | + /> | |
43 | + | |
44 | + <SNMPDescription | |
45 | + :record="getTransportInfo" | |
46 | + v-if="getTransportInfo.type === TransportTypeEnum.SNMP" | |
47 | + /> | |
48 | + | |
49 | + <TCPDescription | |
50 | + :record="getTransportInfo" | |
51 | + v-if="getTransportInfo.type === TransportTypeEnum.TCP" | |
52 | + /> | |
53 | + </section> | |
54 | +</template> | ... | ... |
1 | +export enum TransportTypeEnum { | |
2 | + DEFAULT = 'DEFAULT', | |
3 | + MQTT = 'MQTT', | |
4 | + COAP = 'COAP', | |
5 | + LWM2M = 'LWM2M', | |
6 | + SNMP = 'SNMP', | |
7 | + TCP = 'TCP', | |
8 | +} | |
9 | + | |
10 | +export enum TransportPayloadTypeEnum { | |
11 | + PROTOBUF = 'PROTOBUF', | |
12 | + JSON = 'JSON', | |
13 | +} | |
14 | + | |
15 | +export enum COAPDeviceTypeEnum { | |
16 | + DEFAULT = 'DEFAULT', | |
17 | + EFENTO = 'EFENTO', | |
18 | +} | |
19 | + | |
20 | +export enum COAPDeviceTypeNameEnum { | |
21 | + DEFAULT = '默认', | |
22 | + EFENTO = 'Efento NB-IoT', | |
23 | +} | |
24 | + | |
25 | +export enum PowerModeEnum { | |
26 | + PSM = 'PSM', | |
27 | + DRX = 'DRX', | |
28 | + E_DRX = 'E_DRX', | |
29 | +} | |
30 | + | |
31 | +export enum PowerModeNameEnum { | |
32 | + PSM = 'Power Saving Mode (PSM)', | |
33 | + DRX = 'Discontinuous Reception (DRX)', | |
34 | + E_DRX = 'Extended Discontinuous Reception (eDRX)', | |
35 | +} | |
36 | + | |
37 | +export enum TimeUnitEnum { | |
38 | + MILLISECONDS = 'milliseconds', | |
39 | + SECOND = 'second', | |
40 | + MINUTE = 'minute', | |
41 | + HOUR = 'hour', | |
42 | +} | |
43 | + | |
44 | +export enum SecurityModeNameEnum { | |
45 | + NO_SEC = 'No Security', | |
46 | + PSK = 'Pre-Shared Key', | |
47 | + RPK = 'Raw Public Key', | |
48 | + X509 = 'X.509 Certificate', | |
49 | +} | |
50 | + | |
51 | +export enum BindingNameEnum { | |
52 | + U = 'U: Client is reachable via the UDP binding at any time.', | |
53 | + M = 'M: Client is reachable via the MQTT binding at any time.', | |
54 | + H = 'H: Client is reachable via the HTTP binding at any time.', | |
55 | + T = 'T: Client is reachable via the TCP binding at any time.', | |
56 | + S = 'S: Client is reachable via the SMS binding at any time.', | |
57 | + N = 'N: Client MUST send the response to such a request over the Non-IP binding (is supported since LWM', | |
58 | + UQ = 'UQ: UDP connection in queue mode (is not supported since LWM2M 1.1)', | |
59 | + UQS = 'UQS: both UDP and SMS connections active; UDP in queue mode, SMS in standard mode (is not supported since LWM2M 1.1)', | |
60 | + TQ = 'TQ: TCP connection in queue mode (is not supported since LWM2M 1.1)', | |
61 | + TQS = 'TQS: both TCP and SMS connections active; TCP in queue mode, SMS in standard mode (is not supported since LWM2M 1.1)\t', | |
62 | + SQ = 'SQ: SMS connection in queue mode (is not supported since LWM2M 1.1)', | |
63 | +} | |
64 | + | |
65 | +export const FirmwareUpdateStrategyNameEnum = { | |
66 | + 1: 'Push firmware update as binary file using Object 5 and Resource 0 (Package)', | |
67 | + 2: 'Auto-generate unique CoAP URL to download the package and push firmware update as Object 5 and', | |
68 | + 3: 'Push firmware update as binary file using Object 19 and Resource 0 (Data)', | |
69 | +}; | |
70 | + | |
71 | +export const SoftwareUpdateStrategyNameEnum = { | |
72 | + 1: 'Push binary file using Object 9 and Resource 2 (Package)', | |
73 | + 2: 'Auto-generate unique CoAP URL to download the package and push software update using Object 9 and', | |
74 | +}; | |
75 | + | |
76 | +export enum SNMPRangeNameEnum { | |
77 | + TELEMETRY_QUERYING = 'Telemetry', | |
78 | + CLIENT_ATTRIBUTES_QUERYING = 'Client attributes', | |
79 | + SHARED_ATTRIBUTES_SETTING = 'Shared attributes', | |
80 | + TO_DEVICE_RPC_REQUEST = 'RPC request', | |
81 | +} | |
82 | + | |
83 | +export enum SNMPDataTypeEnum { | |
84 | + STRING = '字符串', | |
85 | + LONG = '数字', | |
86 | + BOOLEAN = '布尔值', | |
87 | + DOUBLE = '双精度小数', | |
88 | + JSON = 'JSON', | |
89 | +} | ... | ... |
1 | +export { default as TransportDescription } from './TransportDescription.vue'; | ... | ... |
... | ... | @@ -9,17 +9,33 @@ |
9 | 9 | </div> |
10 | 10 | <div class="form-item2" :style="{ height: dynamicHeight + 'vh' }"> |
11 | 11 | <div style="margin-left: 1vw"> |
12 | - <h3 v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" style="color: gray"> | |
13 | - 查询频率(毫秒*)</h3> | |
14 | - <InputNumber v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" | |
15 | - v-model:value="queryingFrequencyMs" :min="0" :max="99999999999999999999" style="margin-top: 0.25vh" /> | |
12 | + <h3 | |
13 | + v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" | |
14 | + style="color: gray" | |
15 | + > | |
16 | + 查询频率(毫秒*)</h3 | |
17 | + > | |
18 | + <InputNumber | |
19 | + v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" | |
20 | + v-model:value="queryingFrequencyMs" | |
21 | + :min="0" | |
22 | + :max="99999999999999999999" | |
23 | + style="margin-top: 0.25vh" | |
24 | + /> | |
16 | 25 | <div style="margin-top: 0.65vh"></div> |
17 | - <MappingsForm :value="item.mappings" @change="handleMappingsChange" @dynamicAddHeight="dynamicHeight += 4" | |
18 | - @dynamicReduceHeight="dynamicHeight -= 4" /> | |
26 | + <MappingsForm | |
27 | + :value="item.mappings" | |
28 | + @change="handleMappingsChange" | |
29 | + @dynamicAddHeight="dynamicHeight += 4" | |
30 | + @dynamicReduceHeight="dynamicHeight -= 4" | |
31 | + /> | |
19 | 32 | </div> |
20 | 33 | </div> |
21 | 34 | <div class="form-item3" :style="{ height: dynamicHeight + 'vh' }"> |
22 | - <div style="text-align: center; line-height: 20vh" :style="{ lineHeight: dynamicHeight + 'vh' }"> | |
35 | + <div | |
36 | + style="text-align: center; line-height: 20vh" | |
37 | + :style="{ lineHeight: dynamicHeight + 'vh' }" | |
38 | + > | |
23 | 39 | <Button size="small" type="default" @click="handleRemove(item, index)"> |
24 | 40 | <template #icon> |
25 | 41 | <MinusCircleOutlined /> |
... | ... | @@ -30,105 +46,105 @@ |
30 | 46 | </div> |
31 | 47 | </template> |
32 | 48 | <script setup lang="ts"> |
33 | -import { ref } from 'vue'; | |
34 | -import { Button, InputNumber } from 'ant-design-vue'; | |
35 | -import { MinusCircleOutlined } from '@ant-design/icons-vue'; | |
36 | -import MappingsForm from './MappingsForm.vue'; | |
37 | -import { useMessage } from '/@/hooks/web/useMessage'; | |
49 | + import { ref } from 'vue'; | |
50 | + import { Button, InputNumber } from 'ant-design-vue'; | |
51 | + import { MinusCircleOutlined } from '@ant-design/icons-vue'; | |
52 | + import MappingsForm from './MappingsForm.vue'; | |
53 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
38 | 54 | |
39 | -const props = defineProps({ | |
40 | - item: { | |
41 | - type: Object, | |
42 | - default: () => { }, | |
43 | - }, | |
44 | - index: { | |
45 | - type: Number, | |
46 | - }, | |
47 | -}); | |
48 | -const emit = defineEmits(['removeItem']); | |
49 | -const dynamicHeight = ref(25); | |
50 | -const queryingFrequencyMs = ref(5000); | |
51 | -const { createMessage } = useMessage(); | |
52 | -const handleMappingsChange = (e) => { | |
53 | - // eslint-disable-next-line vue/no-mutating-props | |
54 | - props.item.mappings = e; | |
55 | -}; | |
56 | -const handleRemove = (item, index) => { | |
57 | - emit('removeItem', item, index); | |
58 | -}; | |
59 | -//设置回显的高度 | |
60 | -const setFieldsValueFunc = () => { | |
61 | - dynamicHeight.value = props.item.mappings.length * 3 + props.item.mappings.length + 15; | |
62 | - queryingFrequencyMs.value = props.item.queryingFrequencyMs; | |
63 | -}; | |
64 | -//获取表单的值 | |
65 | -const getSnmpFormFunc = () => { | |
66 | - if (!props.item.spec || props.item.spec == '' || props.item.spec == undefined) { | |
67 | - return createMessage.error('请选择范围'); | |
68 | - } | |
69 | - if ( | |
70 | - props.item.spec == 'TELEMETRY_QUERYING' || | |
71 | - props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
72 | - ) { | |
73 | - if (queryingFrequencyMs.value == null) { | |
74 | - return createMessage.error('请填写查询频率'); | |
75 | - } | |
76 | - } | |
77 | - let obj: any = {}; | |
78 | - obj = { | |
79 | - ...{ spec: props.item.spec }, | |
80 | - ...{ mappings: props.item.mappings }, | |
81 | - ...{ | |
82 | - queryingFrequencyMs: | |
83 | - props.item.spec == 'TELEMETRY_QUERYING' || props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
84 | - ? queryingFrequencyMs.value | |
85 | - : null, | |
55 | + const props = defineProps({ | |
56 | + item: { | |
57 | + type: Object, | |
58 | + default: () => {}, | |
86 | 59 | }, |
60 | + index: { | |
61 | + type: Number, | |
62 | + }, | |
63 | + }); | |
64 | + const emit = defineEmits(['removeItem']); | |
65 | + const dynamicHeight = ref(25); | |
66 | + const queryingFrequencyMs = ref(5000); | |
67 | + const { createMessage } = useMessage(); | |
68 | + const handleMappingsChange = (e) => { | |
69 | + // eslint-disable-next-line vue/no-mutating-props | |
70 | + props.item.mappings = e; | |
71 | + }; | |
72 | + const handleRemove = (item, index) => { | |
73 | + emit('removeItem', item, index); | |
74 | + }; | |
75 | + //设置回显的高度 | |
76 | + const setFieldsValueFunc = () => { | |
77 | + dynamicHeight.value = props.item.mappings.length * 3 + props.item.mappings.length + 15; | |
78 | + queryingFrequencyMs.value = props.item.queryingFrequencyMs; | |
87 | 79 | }; |
88 | - return obj; | |
89 | -}; | |
90 | -defineExpose({ | |
91 | - getSnmpFormFunc, | |
92 | - setFieldsValueFunc, | |
93 | - handleMappingsChange, | |
94 | -}); | |
80 | + //获取表单的值 | |
81 | + const getSnmpFormFunc = () => { | |
82 | + if (!props.item.spec || props.item.spec == '' || props.item.spec == undefined) { | |
83 | + return createMessage.error('请选择范围'); | |
84 | + } | |
85 | + if ( | |
86 | + props.item.spec == 'TELEMETRY_QUERYING' || | |
87 | + props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
88 | + ) { | |
89 | + if (queryingFrequencyMs.value == null) { | |
90 | + return createMessage.error('请填写查询频率'); | |
91 | + } | |
92 | + } | |
93 | + let obj: any = {}; | |
94 | + obj = { | |
95 | + ...{ spec: props.item.spec }, | |
96 | + ...{ mappings: props.item.mappings }, | |
97 | + ...{ | |
98 | + queryingFrequencyMs: | |
99 | + props.item.spec == 'TELEMETRY_QUERYING' || props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
100 | + ? queryingFrequencyMs.value | |
101 | + : null, | |
102 | + }, | |
103 | + }; | |
104 | + return obj; | |
105 | + }; | |
106 | + defineExpose({ | |
107 | + getSnmpFormFunc, | |
108 | + setFieldsValueFunc, | |
109 | + handleMappingsChange, | |
110 | + }); | |
95 | 111 | </script> |
96 | 112 | <style lang="less" scoped> |
97 | -::-webkit-scrollbar { | |
98 | - display: none; | |
99 | - width: 0 !important; | |
100 | - height: 0 !important; | |
101 | - -webkit-appearance: none; | |
102 | - background: transparent; | |
103 | -} | |
104 | - | |
105 | -.snmp-form { | |
106 | - display: flex; | |
107 | - align-items: center; | |
108 | - justify-content: space-between; | |
109 | - width: 40vw; | |
110 | - height: 20vh; | |
111 | - border: 0.1px solid #bfbfbf; | |
112 | - margin-top: 2vh; | |
113 | - | |
114 | - .form-item1 { | |
115 | - width: 9vw; | |
116 | - height: 20vh; | |
117 | - border: 0.1px solid #bfbfbf; | |
113 | + ::-webkit-scrollbar { | |
114 | + display: none; | |
115 | + width: 0 !important; | |
116 | + height: 0 !important; | |
117 | + -webkit-appearance: none; | |
118 | + background: transparent; | |
118 | 119 | } |
119 | 120 | |
120 | - .form-item2 { | |
121 | - width: 28vw; | |
121 | + .snmp-form { | |
122 | + display: flex; | |
123 | + align-items: center; | |
124 | + justify-content: space-between; | |
125 | + width: 40vw; | |
122 | 126 | height: 20vh; |
123 | 127 | border: 0.1px solid #bfbfbf; |
124 | - overflow: hidden; | |
125 | - overflow-y: scroll; | |
126 | - } | |
128 | + margin-top: 2vh; | |
127 | 129 | |
128 | - .form-item3 { | |
129 | - width: 2vw; | |
130 | - height: 20vh; | |
131 | - border: 0.1px solid #bfbfbf; | |
130 | + .form-item1 { | |
131 | + width: 9vw; | |
132 | + height: 20vh; | |
133 | + border: 0.1px solid #bfbfbf; | |
134 | + } | |
135 | + | |
136 | + .form-item2 { | |
137 | + width: 28vw; | |
138 | + height: 20vh; | |
139 | + border: 0.1px solid #bfbfbf; | |
140 | + overflow: hidden; | |
141 | + overflow-y: scroll; | |
142 | + } | |
143 | + | |
144 | + .form-item3 { | |
145 | + width: 2vw; | |
146 | + height: 20vh; | |
147 | + border: 0.1px solid #bfbfbf; | |
148 | + } | |
132 | 149 | } |
133 | -} | |
134 | 150 | </style> | ... | ... |