Showing
5 changed files
with
255 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): 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,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]) }); | ||
| 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() |