Skip to content

Commit

Permalink
feat(tag, monitoring): support BYTES type and wirte BYTES value
Browse files Browse the repository at this point in the history
  • Loading branch information
orangegzx authored and ysfscream committed Sep 4, 2023
1 parent c9481e7 commit c68bc13
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 33 deletions.
17 changes: 5 additions & 12 deletions src/composables/config/useAddTagCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useRoute } from 'vue-router'
import { EmqxMessage } from '@emqx/emqx-ui'
import type { TagFormItem, TagForm, TagData } from '@/types/config'
import { TagType, TagAttributeType } from '@/types/enums'
import { getErrorMsg, popUpErrorMessage, dataType, createRandomString } from '@/utils/utils'
import { dataType, createRandomString } from '@/utils/utils'
import useWriteDataCheckNParse from '@/composables/data/useWriteDataCheckNParse'

export const useTagTypeSelect = () => {
Expand Down Expand Up @@ -151,7 +151,7 @@ export const createTagForm = () => {
type: null,
// for the key when use v-for
id: createRandomString(6),
decimal: null,
decimal: undefined,
description: '',
precision: undefined,
value: undefined,
Expand Down Expand Up @@ -181,10 +181,12 @@ export const useHandleTagValue = () => {
handleTagValue,
}
}

export default () => {
const route = useRoute()
const { t } = useI18n()

const { handleTagValue } = useHandleTagValue()
const groupName = computed(() => route.params.group as string)

const sliceTagList = (list: TagFormItem[], errIndex: number) => {
Expand Down Expand Up @@ -218,18 +220,9 @@ export default () => {
}
}

const { parseWriteData } = useWriteDataCheckNParse()
const parseTagData = async (tagList: TagFormItem[]): Promise<TagForm[]> => {
const tags: TagForm[] = tagList.map(({ id, ...tagData }) => {
const data = tagData
const { type, value } = data
if (value !== undefined && value !== null) {
/** let it go, when the tags value use hexadecimal, and sync EditTagDialog.vue
* const newValue = isUseHexadecimal.value ? await transToDecimal({ ...tagData, value } as TagDataInTable): value
*/
data.value = parseWriteData(Number(type), String(value))
}

const data = handleTagValue(tagData)
return data
})
return tags
Expand Down
10 changes: 8 additions & 2 deletions src/composables/config/useTagForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default (props: any) => {
}

// checkFloat,
const { checkWriteData } = useWriteDataCheckNParse()
const { checkWriteData } = useWriteDataCheckNParse(false)
const createErrorMsg = (type: number, prefix: string, suffix: string) => {
if (!type) return ''
return prefix + TagType[type] + suffix
Expand Down Expand Up @@ -99,7 +99,6 @@ export default (props: any) => {
const { field } = rule
const $index = field.split('.')[1]
const tag: TagDataInTable = props?.data?.tagList ? props.data.tagList[$index] : props?.data
// const { type, attribute, decimal } = tag
const { type, attribute } = tag

try {
Expand Down Expand Up @@ -127,6 +126,13 @@ export default (props: any) => {
const errorMsg = errorMsgMap.value(type)[Number('1') as keyof typeof errorMsgMap.value]
return callback(new Error(errorMsg))
}

// validate bytes value length; when `static` support `bytes` support, let comment go
// const bytesValue = JSON.parse(trueValue)
// if (type === TagType.BYTES && bytesValue.length > 128) {
// // checkWriteData(bytes) has valid `value` is `Array`
// return callback(new Error(t('data.arrayLengthError', { length: 128 })))
// }
return callback()
}

Expand Down
2 changes: 1 addition & 1 deletion src/composables/data/useDataMonitoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ export default () => {
}
return value
}
if (type === TagType.BYTE || type === TagType.BOOL || type === TagType.BIT || type === TagType.STRING) {
if (type === TagType.BYTES || type === TagType.BOOL || type === TagType.BIT || type === TagType.STRING) {
return value
}
const data = await transToHexadecimal(tagData)
Expand Down
51 changes: 43 additions & 8 deletions src/composables/data/useWriteDataCheckNParse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ STRING 15 string

import { TagType } from '@/types/enums'
import { HEXADECIMAL_PREFIX } from '@/utils/constants'
import { HEXADECIMAL_REGEX, FLOAT_REGEX, BIT_REGEX, INT_REGEX } from '@/utils/regexps'
import { BYTES_REGEX, FLOAT_REGEX, BIT_REGEX, INT_REGEX } from '@/utils/regexps'
import {
transFloatNumberToHex,
transNegativeNumberToHex,
Expand All @@ -31,21 +31,23 @@ import {
transIntHexToDecimalNum,
} from './convert'
import type { TagDataInTable } from './useDataMonitoring'
import { isJSONData } from '@/utils/utils'

export enum WriteDataErrorCode {
FormattingError = 1,
LessThanMinimum,
GreaterThanMaximum,
LessThanMinSafeInteger,
GreaterThanMaxSafeInteger,
BYTESValueLengthError,
}

interface RangeObj {
MIN: number
MAX: number
}

export default () => {
export default (isWriteValue = true) => {
const createIntTypeRange = (bitsNum: number): RangeObj => {
return {
MIN: -(2 ** (bitsNum - 1)),
Expand All @@ -64,15 +66,43 @@ export default () => {
const INT32_RANGE = createIntTypeRange(32)
const INT64_RANGE = createIntTypeRange(64)

const BYTES_RANGE = createUIntTypeRange(8)
const UINT8_RANGE = createUIntTypeRange(8)
const UINT16_RANGE = createUIntTypeRange(16)
const UINT32_RANGE = createUIntTypeRange(32)
const UINT64_RANGE = createUIntTypeRange(64)

const checkByte = (value: string): Promise<boolean | Error> =>
HEXADECIMAL_REGEX.test(value.replace(/\s/g, ''))
? Promise.resolve(true)
: Promise.reject(new Error(WriteDataErrorCode.FormattingError.toString()))
const checkByte = async (value: string): Promise<boolean | Error> => {
// Static attribute do not currently support BYTES type, when creat a tag
if (!isWriteValue) return Promise.resolve(true)

try {
await isJSONData(value)
const arrValue = JSON.parse(value)
console.log('arrValue', arrValue)
if (!Array.isArray(arrValue)) {
return Promise.reject(new Error(WriteDataErrorCode.FormattingError.toString()))
}

const isElementAllInRange = arrValue.every((v: string | number) => {
const isIntNumber = BYTES_REGEX.test(String(v))
const isInRange = Number(v) >= BYTES_RANGE.MIN && Number(v) <= BYTES_RANGE.MAX

return isIntNumber && isInRange
})
if (!isElementAllInRange) {
return Promise.reject(new Error(WriteDataErrorCode.FormattingError.toString()))
}

if (arrValue.length > 128) {
return Promise.reject(new Error(WriteDataErrorCode.BYTESValueLengthError.toString()))
}
} catch (error) {
return Promise.reject(new Error(WriteDataErrorCode.FormattingError.toString()))
}

return Promise.resolve(true)
}

const checkBit = (value: string): Promise<boolean | Error> =>
BIT_REGEX.test(value)
Expand Down Expand Up @@ -120,7 +150,7 @@ export default () => {

const check = (type: TagType, value: string) => {
const checkMap = {
[TagType.BYTE]: checkByte.bind(null, value),
[TagType.BYTES]: checkByte.bind(null, value),
[TagType.INT8]: checkInt.bind(null, INT8_RANGE, value),
[TagType.INT16]: checkInt.bind(null, INT16_RANGE, value),
[TagType.INT32]: checkInt.bind(null, INT32_RANGE, value),
Expand All @@ -142,9 +172,14 @@ export default () => {
}

const parseWriteData = (type: TagType, value: string) => {
if (type === TagType.BYTE || type === TagType.STRING || type === TagType.BOOL) {
if (type === TagType.STRING || type === TagType.BOOL) {
return value
}

if (type === TagType.BYTES) {
return value ? JSON.parse(value) : value
}

return Number(value)
}
const checkWriteData = async (type: number, value: string): Promise<boolean | Error> => {
Expand Down
12 changes: 7 additions & 5 deletions src/composables/data/useWriteDataDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default (props: Props) => {
),
[WriteDataErrorCode.LessThanMinSafeInteger]: t('data.writeDataSafeMinimumError'),
[WriteDataErrorCode.GreaterThanMaxSafeInteger]: t('data.writeDataSafeMaximumError'),
[WriteDataErrorCode.BYTESValueLengthError]: t('data.arrayLengthError', { length: 128 }),
}))

const inputValue = ref('')
Expand All @@ -63,7 +64,7 @@ export default (props: Props) => {
const showToggleHexadecimalSwitch = computed(() => {
return (
props.tag?.type &&
props.tag.type !== TagType.BYTE &&
props.tag.type !== TagType.BYTES &&
props.tag.type !== TagType.BOOL &&
props.tag.type !== TagType.BIT &&
props.tag.type !== TagType.STRING
Expand Down Expand Up @@ -103,10 +104,11 @@ export default (props: Props) => {
return Promise.resolve()
}

const checkValueRes = await Promise.allSettled([
checkFloat.bind(null, trueValue)(),
checkWriteData(type, trueValue),
])
const requests = [checkWriteData(type, trueValue)]
if (type !== TagType.BYTES) {
requests.push(checkFloat.bind(null, trueValue)())
}
const checkValueRes = await Promise.allSettled(requests)
const checkRes = checkValueRes.map((item: any) => item?.value || false)
if (!checkRes.includes(true)) {
inputErrorMsg.value = errorMsgMap.value[Number('1') as keyof typeof errorMsgMap.value]
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,4 +594,12 @@ export default {
zh: '请选择南向驱动数据',
en: 'Please select the south drive data',
},
staticNotSupportBytes: {
zh: 'Static 属性暂不支持 BYTES 类型',
en: 'Static attribute do not currently support BYTES type',
},
arrayFormatError: {
zh: '请输入数组',
en: 'Please enter an array',
},
}
4 changes: 4 additions & 0 deletions src/i18n/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export default {
zh: ' 内容格式错误',
en: ' content format error',
},
arrayLengthError: {
zh: '请输入长度不大于 {length} 的数据',
en: 'Please enter data no longer than {length}',
},
writeDataMinimumErrorPrefix: {
zh: '小于数据类型 ',
en: 'Less than the minimum value of data type ',
Expand Down
2 changes: 1 addition & 1 deletion src/types/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export enum TagType {
BIT,
BOOL,
STRING,
BYTE,
BYTES,
WORD = 16,
DWORD,
LWORD,
Expand Down
1 change: 1 addition & 0 deletions src/utils/regexps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const DECIMAL_POSITIVE_REGEX = /^[0-9]\d*$/
export const FLOAT_REGEX = /^-?\d*\.?\d+(e-?\d+)?$/
export const BIT_REGEX = /^[0-9a-f]+$/
export const INT_REGEX = /^-?\d+$/
export const BYTES_REGEX = /^[0-9]+$/
export const BINARY_STRING_REGEX = /^(0|1)+$/

export const UPPER_LOWERCASE_REGEX = /^[A-Z][a-z]+$/
Expand Down
2 changes: 1 addition & 1 deletion src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export const isTheSameParentRoute = (from: any, to: any) => {
export const isJSONData = (data: string) => {
try {
JSON.parse(data)
return Promise.resolve()
return Promise.resolve(true)
} catch (error) {
console.error(error)
return Promise.reject(error)
Expand Down
2 changes: 0 additions & 2 deletions src/views/config/southDriver/components/EditTagDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import TagFormCom from './TagForm.vue'
import type { PluginInfo, TagData } from '@/types/config'
import { updateTag } from '@/api/config'
import { useI18n } from 'vue-i18n'
import useWriteDataCheckNParse from '@/composables/data/useWriteDataCheckNParse'
import { useNodePluginInfo } from '@/composables/config/usePluginInfo'
import { useHandleTagValue } from '@/composables/config/useAddTagCommon'
Expand All @@ -52,7 +51,6 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue', 'submitted'])
const { t } = useI18n()
const { parseWriteData } = useWriteDataCheckNParse()
const { getNodePluginInfo } = useNodePluginInfo()
const pluginMsg: Ref<undefined | PluginInfo> = ref(undefined)
Expand Down
24 changes: 24 additions & 0 deletions src/views/config/southDriver/components/TagForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
</emqx-col>
<emqx-col :span="12">
<emqx-form-item :label="$t('common.attribute')" prop="attribute" required>
<template #label>
<span>{{ $t('common.attribute') }}</span>
<AComWithDesc :content="$t('config.staticNotSupportBytes')">
<i class="el-icon-info icon-label" />
</AComWithDesc>
</template>
<TagAttributeSelect v-model="form.attribute" @change="changeAttribute" />
</emqx-form-item>
</emqx-col>
Expand All @@ -19,6 +25,7 @@
:key="item.value"
:value="item.value"
:label="item.label"
:disabled="item.value === TagType.BYTES && isAttrsIncludeStatic(form.attribute)"
/>
</emqx-select>
</emqx-form-item>
Expand Down Expand Up @@ -81,6 +88,8 @@ import { useTagPrecision } from '@/composables/config/useAddTagCommon'
import TagAttributeSelect from './TagAttributeSelect.vue'
import type { PluginInfo, TagForm } from '@/types/config'
import useTagForm from '@/composables/config/useTagForm'
import { TagType } from '@/types/enums'
import AComWithDesc from '@/components/AComWithDesc.vue'
const props = defineProps({
data: {
Expand Down Expand Up @@ -109,6 +118,8 @@ const form: WritableComputedRef<TagForm> = computed({
},
})
const isBYTESType = computed(() => form.value.type === TagType.BYTES)
const changeAttribute = () => {
const isStaticAttr = isAttrsIncludeStatic.value(form.value.attribute)
Expand All @@ -117,6 +128,9 @@ const changeAttribute = () => {
} else {
form.value.precision = undefined
form.value.decimal = null
if (isBYTESType.value) {
form.value.type = null
}
}
// validate 'address'
nextTick(() => {
Expand Down Expand Up @@ -145,3 +159,13 @@ defineExpose({
resetFields,
})
</script>

<style lang="scss" scoped>
:deep(.el-form-item__label) {
float: none;
}
.icon-label {
padding-left: 4px;
color: #999;
}
</style>
Loading

0 comments on commit c68bc13

Please sign in to comment.