Showing
5 changed files
with
255 additions
and
17 deletions
... | ... | @@ -166,6 +166,7 @@ export interface DeviceRecord { |
166 | 166 | id: string; |
167 | 167 | creator: string; |
168 | 168 | createTime: string; |
169 | + codeType?: string; | |
169 | 170 | name: string; |
170 | 171 | tenantId: string; |
171 | 172 | transportType: string; |
... | ... | @@ -199,6 +200,8 @@ export interface DeviceModelOfMatterAttrs { |
199 | 200 | identifier: string; |
200 | 201 | accessMode: string; |
201 | 202 | detail: StructJSON; |
203 | + deviceDetail?: DeviceRecord; | |
204 | + extensionDesc?: any; | |
202 | 205 | } |
203 | 206 | |
204 | 207 | export interface DeviceStateLogModel { | ... | ... |
... | ... | @@ -238,7 +238,7 @@ |
238 | 238 | const handleSendCommandModal = (data: DataSource) => { |
239 | 239 | openSendCommandModal(true, { |
240 | 240 | mode: DataActionModeEnum.READ, |
241 | - record: { ...toRaw(data.detail) }, | |
241 | + record: { ...toRaw(data.detail), deviceDetail: props.deviceDetail as any }, | |
242 | 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): FormSchema[] => { | |
131 | + const { identifier, functionName } = schemas; | |
132 | + if (identifier == '06') { | |
133 | + return [ | |
134 | + { | |
135 | + field: identifier, | |
136 | + label: functionName, | |
137 | + component: 'InputNumber', | |
138 | + rules: [{ required: true, message: '请输入值' }], | |
139 | + componentProps: { | |
140 | + precision: 0, | |
141 | + placeholder: `请输入整数`, | |
142 | + }, | |
143 | + }, | |
144 | + ]; | |
145 | + } else if (identifier == '05') { | |
146 | + return [ | |
147 | + { | |
148 | + field: identifier, | |
149 | + label: functionName, | |
150 | + component: 'InputNumber', | |
151 | + rules: [{ required: true, message: '请输入值' }], | |
152 | + componentProps: { | |
153 | + min: 0, | |
154 | + max: 1, | |
155 | + precision: 0, | |
156 | + placeholder: `请输入0或1`, | |
157 | + }, | |
158 | + }, | |
159 | + ]; | |
160 | + } else { | |
161 | + return [ | |
162 | + { | |
163 | + field: identifier, | |
164 | + label: functionName, | |
165 | + component: 'InputNumber', | |
166 | + rules: [{ required: true, message: '请输入值' }], | |
167 | + componentProps: { | |
168 | + placeholder: `请输入值`, | |
169 | + formatter: (e) => | |
170 | + `${e}`.replace(/\B(?=(\d{3})+(?!\d))/g, '').replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3'), | |
171 | + }, | |
172 | + }, | |
173 | + ]; | |
174 | + } | |
175 | +}; | |
176 | + | |
177 | +export { | |
178 | + InsertString, | |
179 | + FillString, | |
180 | + SingleToHex, | |
181 | + FormatHex, | |
182 | + FormatHexBatch, | |
183 | + SingleToHexBatch, | |
184 | + formSchemasConfig, | |
185 | +}; | ... | ... |
... | ... | @@ -10,6 +10,9 @@ |
10 | 10 | import { sendCommandOneway } from '/@/api/dataBoard'; |
11 | 11 | import { useMessage } from '/@/hooks/web/useMessage'; |
12 | 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 | 17 | defineEmits(['register']); |
15 | 18 | const props = defineProps<{ deviceId: string; deviceName: string }>(); |
... | ... | @@ -24,45 +27,93 @@ |
24 | 27 | |
25 | 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 | 35 | const { record } = params; |
29 | - const { name, detail, identifier } = record; | |
36 | + const { name, detail, identifier, deviceDetail, extensionDesc } = record; | |
30 | 37 | const { dataType } = detail; |
31 | 38 | const { type } = dataType || {}; |
39 | + const { codeType } = deviceDetail || {}; | |
40 | + const { registerAddress, actionType } = extensionDesc || {}; | |
41 | + formField.value = identifier; | |
32 | 42 | |
33 | 43 | let schemas = [{ dataType: dataType, identifier, functionName: name } as StructJSON]; |
34 | 44 | |
35 | 45 | if (type === DataTypeEnum.IS_STRUCT) { |
36 | 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]) }); | |
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 | 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 | 82 | const { createMessage } = useMessage(); |
49 | 83 | const loading = ref(false); |
50 | 84 | const handleSend = async () => { |
51 | 85 | try { |
52 | 86 | loading.value = true; |
53 | 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 | 107 | await sendCommandOneway({ |
59 | 108 | deviceId: props.deviceId, |
60 | 109 | value: { |
61 | 110 | persistent: true, |
62 | 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 | 119 | createMessage.success('属性下发成功~'); | ... | ... |