Commit 444d7d510ea2b7cee7b55eb7c38fdfda1be490c5
Merge branch 'perf/attribute-distribution' into 'main_dev'
Perf: 修改设备物模型数据自定义和ModBUS属性下发方式 See merge request yunteng/thingskit-front!781
Showing
5 changed files
with
256 additions
and
17 deletions
@@ -166,6 +166,7 @@ export interface DeviceRecord { | @@ -166,6 +166,7 @@ export interface DeviceRecord { | ||
166 | id: string; | 166 | id: string; |
167 | creator: string; | 167 | creator: string; |
168 | createTime: string; | 168 | createTime: string; |
169 | + codeType?: string; | ||
169 | name: string; | 170 | name: string; |
170 | tenantId: string; | 171 | tenantId: string; |
171 | transportType: string; | 172 | transportType: string; |
@@ -199,6 +200,8 @@ export interface DeviceModelOfMatterAttrs { | @@ -199,6 +200,8 @@ export interface DeviceModelOfMatterAttrs { | ||
199 | identifier: string; | 200 | identifier: string; |
200 | accessMode: string; | 201 | accessMode: string; |
201 | detail: StructJSON; | 202 | detail: StructJSON; |
203 | + deviceDetail?: DeviceRecord; | ||
204 | + extensionDesc?: any; | ||
202 | } | 205 | } |
203 | 206 | ||
204 | export interface DeviceStateLogModel { | 207 | export interface DeviceStateLogModel { |
@@ -238,7 +238,7 @@ | @@ -238,7 +238,7 @@ | ||
238 | const handleSendCommandModal = (data: DataSource) => { | 238 | const handleSendCommandModal = (data: DataSource) => { |
239 | openSendCommandModal(true, { | 239 | openSendCommandModal(true, { |
240 | mode: DataActionModeEnum.READ, | 240 | mode: DataActionModeEnum.READ, |
241 | - record: { ...toRaw(data.detail) }, | 241 | + record: { ...toRaw(data.detail), deviceDetail: props.deviceDetail as any }, |
242 | } as ModalParamsType); | 242 | } as ModalParamsType); |
243 | }; | 243 | }; |
244 | 244 |
1 | +import { FormSchema } from '/@/components/Form'; | ||
2 | + | ||
3 | +const InsertString = (t, c, n) => { | ||
4 | + const r: string | number[] = []; | ||
5 | + | ||
6 | + for (let i = 0; i * 2 < t.length; i++) { | ||
7 | + r.push(t.substr(i * 2, n)); | ||
8 | + } | ||
9 | + return r.join(c); | ||
10 | +}; | ||
11 | +const FillString = (t, c, n, b) => { | ||
12 | + if (t == '' || c.length != 1 || n <= t.length) { | ||
13 | + return t; | ||
14 | + } | ||
15 | + const l = t.length; | ||
16 | + | ||
17 | + for (let i = 0; i < n - l; i++) { | ||
18 | + if (b == true) { | ||
19 | + t = c + t; | ||
20 | + } else { | ||
21 | + t += c; | ||
22 | + } | ||
23 | + } | ||
24 | + return t; | ||
25 | +}; | ||
26 | +const SingleToHex = (t) => { | ||
27 | + if (t == '') { | ||
28 | + return ''; | ||
29 | + } | ||
30 | + t = parseFloat(t); | ||
31 | + | ||
32 | + if (isNaN(t) == true) { | ||
33 | + return 'Error'; | ||
34 | + } | ||
35 | + if (t == 0) { | ||
36 | + return '00000000'; | ||
37 | + } | ||
38 | + let s, e, m; | ||
39 | + | ||
40 | + if (t > 0) { | ||
41 | + s = 0; | ||
42 | + } else { | ||
43 | + s = 1; | ||
44 | + | ||
45 | + t = 0 - t; | ||
46 | + } | ||
47 | + m = t.toString(2); | ||
48 | + | ||
49 | + if (m >= 1) { | ||
50 | + if (m.indexOf('.') == -1) { | ||
51 | + m = m + '.0'; | ||
52 | + } | ||
53 | + e = m.indexOf('.') - 1; | ||
54 | + } else { | ||
55 | + e = 1 - m.indexOf('1'); | ||
56 | + } | ||
57 | + if (e >= 0) { | ||
58 | + m = m.replace('.', ''); | ||
59 | + } else { | ||
60 | + m = m.substring(m.indexOf('1')); | ||
61 | + } | ||
62 | + if (m.length > 24) { | ||
63 | + m = m.substr(0, 24); | ||
64 | + } else { | ||
65 | + m = FillString(m, '0', 24, false); | ||
66 | + } | ||
67 | + m = m.substring(1); | ||
68 | + | ||
69 | + e = (e + 127).toString(2); | ||
70 | + | ||
71 | + e = FillString(e, '0', 8, true); | ||
72 | + | ||
73 | + let r = parseInt(s + e + m, 2).toString(16); | ||
74 | + | ||
75 | + r = FillString(r, '0', 8, true); | ||
76 | + | ||
77 | + return InsertString(r, ' ', 2).toUpperCase(); | ||
78 | +}; | ||
79 | + | ||
80 | +const FormatHex = (t, n, ie) => { | ||
81 | + const r: string[] = []; | ||
82 | + | ||
83 | + let s = ''; | ||
84 | + | ||
85 | + let c = 0; | ||
86 | + | ||
87 | + for (let i = 0; i < t.length; i++) { | ||
88 | + if (t.charAt(i) != ' ') { | ||
89 | + s += t.charAt(i); | ||
90 | + | ||
91 | + c += 1; | ||
92 | + | ||
93 | + if (c == n) { | ||
94 | + r.push(s); | ||
95 | + | ||
96 | + s = ''; | ||
97 | + | ||
98 | + c = 0; | ||
99 | + } | ||
100 | + } | ||
101 | + if (ie == false) { | ||
102 | + if (i == t.length - 1 && s != '') { | ||
103 | + r.push(s); | ||
104 | + } | ||
105 | + } | ||
106 | + } | ||
107 | + return r.join('\n'); | ||
108 | +}; | ||
109 | +const FormatHexBatch = (t, n, ie) => { | ||
110 | + const a = t.split('\n'); | ||
111 | + | ||
112 | + const r: string[] = []; | ||
113 | + | ||
114 | + for (let i = 0; i < a.length; i++) { | ||
115 | + r[i] = FormatHex(a[i], n, ie); | ||
116 | + } | ||
117 | + return r.join('\n'); | ||
118 | +}; | ||
119 | +const SingleToHexBatch = (t) => { | ||
120 | + const a = t.split('\n'); | ||
121 | + | ||
122 | + const r: string[] = []; | ||
123 | + | ||
124 | + for (let i = 0; i < a.length; i++) { | ||
125 | + r[i] = SingleToHex(a[i]); | ||
126 | + } | ||
127 | + return r.join('\r\n'); | ||
128 | +}; | ||
129 | + | ||
130 | +const formSchemasConfig = (schemas, actionType): FormSchema[] => { | ||
131 | + const { identifier, functionName } = schemas; | ||
132 | + console.log(identifier, 'identifier', actionType, 'actionType'); | ||
133 | + if (actionType == '06') { | ||
134 | + return [ | ||
135 | + { | ||
136 | + field: identifier, | ||
137 | + label: functionName, | ||
138 | + component: 'InputNumber', | ||
139 | + rules: [{ required: true, message: '请输入值' }], | ||
140 | + componentProps: { | ||
141 | + precision: 0, | ||
142 | + placeholder: `请输入整数`, | ||
143 | + }, | ||
144 | + }, | ||
145 | + ]; | ||
146 | + } else if (actionType == '05') { | ||
147 | + return [ | ||
148 | + { | ||
149 | + field: identifier, | ||
150 | + label: functionName, | ||
151 | + component: 'InputNumber', | ||
152 | + rules: [{ required: true, message: '请输入值' }], | ||
153 | + componentProps: { | ||
154 | + min: 0, | ||
155 | + max: 1, | ||
156 | + precision: 0, | ||
157 | + placeholder: `请输入0或1`, | ||
158 | + }, | ||
159 | + }, | ||
160 | + ]; | ||
161 | + } else { | ||
162 | + return [ | ||
163 | + { | ||
164 | + field: identifier, | ||
165 | + label: functionName, | ||
166 | + component: 'InputNumber', | ||
167 | + rules: [{ required: true, message: '请输入值' }], | ||
168 | + componentProps: { | ||
169 | + placeholder: `请输入值`, | ||
170 | + formatter: (e) => | ||
171 | + `${e}`.replace(/\B(?=(\d{3})+(?!\d))/g, '').replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3'), | ||
172 | + }, | ||
173 | + }, | ||
174 | + ]; | ||
175 | + } | ||
176 | +}; | ||
177 | + | ||
178 | +export { | ||
179 | + InsertString, | ||
180 | + FillString, | ||
181 | + SingleToHex, | ||
182 | + FormatHex, | ||
183 | + FormatHexBatch, | ||
184 | + SingleToHexBatch, | ||
185 | + formSchemasConfig, | ||
186 | +}; |
@@ -10,6 +10,9 @@ | @@ -10,6 +10,9 @@ | ||
10 | import { sendCommandOneway } from '/@/api/dataBoard'; | 10 | import { sendCommandOneway } from '/@/api/dataBoard'; |
11 | import { useMessage } from '/@/hooks/web/useMessage'; | 11 | import { useMessage } from '/@/hooks/web/useMessage'; |
12 | import { unref } from 'vue'; | 12 | import { unref } from 'vue'; |
13 | + import { genModbusCommand } from '/@/api/task'; | ||
14 | + import { TaskTypeEnum } from '/@/views/task/center/config'; | ||
15 | + import { SingleToHex, formSchemasConfig } from './config'; | ||
13 | 16 | ||
14 | defineEmits(['register']); | 17 | defineEmits(['register']); |
15 | const props = defineProps<{ deviceId: string; deviceName: string }>(); | 18 | const props = defineProps<{ deviceId: string; deviceName: string }>(); |
@@ -24,45 +27,93 @@ | @@ -24,45 +27,93 @@ | ||
24 | 27 | ||
25 | const keys = ref<string[]>([]); | 28 | const keys = ref<string[]>([]); |
26 | 29 | ||
27 | - const [register] = useModalInner((params: ModalParamsType<DeviceModelOfMatterAttrs>) => { | 30 | + const modBUSForm = ref<any>({}); |
31 | + const isShowModBUS = ref<Boolean>(false); | ||
32 | + const formField = ref(''); | ||
33 | + | ||
34 | + const [register] = useModalInner(async (params: ModalParamsType<DeviceModelOfMatterAttrs>) => { | ||
28 | const { record } = params; | 35 | const { record } = params; |
29 | - const { name, detail, identifier } = record; | 36 | + const { name, detail, identifier, deviceDetail, extensionDesc } = record; |
30 | const { dataType } = detail; | 37 | const { dataType } = detail; |
31 | const { type } = dataType || {}; | 38 | const { type } = dataType || {}; |
39 | + const { codeType } = deviceDetail || {}; | ||
40 | + const { registerAddress, actionType } = extensionDesc || {}; | ||
41 | + formField.value = identifier; | ||
32 | 42 | ||
33 | let schemas = [{ dataType: dataType, identifier, functionName: name } as StructJSON]; | 43 | let schemas = [{ dataType: dataType, identifier, functionName: name } as StructJSON]; |
34 | 44 | ||
35 | if (type === DataTypeEnum.IS_STRUCT) { | 45 | if (type === DataTypeEnum.IS_STRUCT) { |
36 | schemas = dataType?.specs as StructJSON[]; | 46 | schemas = dataType?.specs as StructJSON[]; |
37 | } | 47 | } |
48 | + if (codeType == TaskTypeEnum.MODBUS) { | ||
49 | + isShowModBUS.value = true; | ||
50 | + modBUSForm.value = { | ||
51 | + crc: 'CRC_16_LOWER', | ||
52 | + deviceCode: '01', | ||
53 | + method: actionType, | ||
54 | + registerAddress, | ||
55 | + registerNumber: 1, | ||
56 | + registerValues: [], | ||
57 | + }; | ||
58 | + setProps({ schemas: formSchemasConfig(schemas[0], actionType) }); | ||
59 | + } else { | ||
60 | + isShowModBUS.value = false; | ||
61 | + const formSchemas = genForm(schemas); | ||
62 | + keys.value = schemas.map((item) => { | ||
63 | + return item.identifier!; | ||
64 | + }); | ||
65 | + setProps({ schemas: formSchemas }); | ||
66 | + } | ||
38 | 67 | ||
39 | - const formSchemas = genForm(schemas); | ||
40 | - | ||
41 | - keys.value = schemas.map((item) => { | ||
42 | - return item.identifier!; | ||
43 | - }); | ||
44 | - setProps({ schemas: formSchemas }); | ||
45 | resetFields(); | 68 | resetFields(); |
46 | }); | 69 | }); |
47 | 70 | ||
71 | + const getArray = (values) => { | ||
72 | + const str = values.replace(/\s+/g, ''); | ||
73 | + const array: any = []; | ||
74 | + | ||
75 | + for (let i = 0; i < str.length; i += 4) { | ||
76 | + const chunk = parseInt(str.substring(i, i + 4), 16); | ||
77 | + array.push(chunk); | ||
78 | + } | ||
79 | + return array; | ||
80 | + }; | ||
81 | + | ||
48 | const { createMessage } = useMessage(); | 82 | const { createMessage } = useMessage(); |
49 | const loading = ref(false); | 83 | const loading = ref(false); |
50 | const handleSend = async () => { | 84 | const handleSend = async () => { |
51 | try { | 85 | try { |
52 | loading.value = true; | 86 | loading.value = true; |
53 | if (!props.deviceId) return; | 87 | if (!props.deviceId) return; |
54 | - const _value = getFieldsValue(); | ||
55 | - const value = unref(keys).reduce((prev, next) => { | ||
56 | - return { ...prev, [next]: _value[next] }; | ||
57 | - }, {}); | 88 | + const sendValue = ref({}); |
89 | + if (unref(isShowModBUS)) { | ||
90 | + //判断tcp类型 标识符是自定义还是ModBus | ||
91 | + const oldValue = getFieldsValue()[unref(formField)]; | ||
92 | + const newValue = getArray(SingleToHex(oldValue)); | ||
93 | + | ||
94 | + modBUSForm.value.registerValues = | ||
95 | + unref(modBUSForm).method != '16' ? [newValue[0]] : newValue; | ||
96 | + modBUSForm.value.registerNumber = unref(modBUSForm).method != '16' ? 1 : 2; | ||
97 | + | ||
98 | + sendValue.value = await genModbusCommand(unref(modBUSForm)); | ||
99 | + } else { | ||
100 | + const _value = getFieldsValue(); | ||
101 | + | ||
102 | + sendValue.value = unref(keys).reduce((prev, next) => { | ||
103 | + return { ...prev, [next]: _value[next] }; | ||
104 | + }, {}); | ||
105 | + } | ||
106 | + | ||
58 | await sendCommandOneway({ | 107 | await sendCommandOneway({ |
59 | deviceId: props.deviceId, | 108 | deviceId: props.deviceId, |
60 | value: { | 109 | value: { |
61 | persistent: true, | 110 | persistent: true, |
62 | method: 'methodThingskit', | 111 | method: 'methodThingskit', |
63 | - params: { | ||
64 | - ...value, | ||
65 | - }, | 112 | + params: unref(isShowModBUS) |
113 | + ? unref(sendValue) | ||
114 | + : { | ||
115 | + ...unref(sendValue), | ||
116 | + }, | ||
66 | }, | 117 | }, |
67 | }); | 118 | }); |
68 | createMessage.success('属性下发成功~'); | 119 | createMessage.success('属性下发成功~'); |
@@ -69,7 +69,6 @@ | @@ -69,7 +69,6 @@ | ||
69 | return hexToDec(props.minValue); | 69 | return hexToDec(props.minValue); |
70 | } | 70 | } |
71 | } | 71 | } |
72 | - | ||
73 | if (unref(inputType) === AddressTypeEnum.DEC) | 72 | if (unref(inputType) === AddressTypeEnum.DEC) |
74 | return `0x${decToHex(unref(getInputValue)!) | 73 | return `0x${decToHex(unref(getInputValue)!) |
75 | .toString() | 74 | .toString() |