更新记录
1.0.5(2024-08-21)
- 增加SLIP沾包粘包处理
1.0.4(2024-07-11)
- 增加获取文件字节数据接口
1.0.3(2024-07-11)
- 增加CRC8、CRC32
平台兼容性
Vue2 | Vue3 |
---|---|
√ | √ |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
HBuilderX 3.6.8,Android:4.4,iOS:9 | √ | √ | √ | √ | √ | √ |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 |
---|---|---|---|
√ | √ | √ | √ |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ |
进制转换、编码转换(ASCII)、modbus、crc(多种类型)、整形工具类(高低位、大小端)、获取文件数据,常用于串口、蓝牙、socket、UDP等字节数据转换
集成插件
- 拷贝demo示例的AndroidManifest.xml到项目根目录(用到了文件读写时需要,没用到文件读写忽略此步骤)
- 集成插件步骤请参考https://www.cnblogs.com/wenrisheng/p/18323027
编码转换
import {
EncodeUtils
} from "@/uni_modules/wrs-uts-modbuscrchex"
- 编码
let str = "银行byteArray为字节数组"; // E993B6E8A18C627974654172726179E4B8BAE5AD97E88A82E695B0E7BB84
let charsetName = "UTF_8"
// 编码
let codeStr = EncodeUtils.encode(str, charsetName)
this.showMsg("encode str:" + str + " encodeStr:" + codeStr)
charsetName:
-
UTF_8:utf8编码,也就是我们常用的ASCII编码,支持所有端
-
US_ASCII:仅支持ios、android
-
ISO_8859_1:仅支持ios、android
-
UTF_16BE:仅支持ios、android
-
UTF_16LE:仅支持ios、android
-
UTF_16:仅支持ios、android
-
UTF_32:仅支持ios
-
UTF_32BE:仅支持ios
-
UTF_32LE:仅支持ios
-
解码
// 解码
let decodeStr = EncodeUtils.decode(codeStr, charsetName)
this.showMsg("decode str:" + codeStr + " decodeStr:" + decodeStr)
crc校验
import {
CRCUtils,HexUtils
} from "@/uni_modules/wrs-uts-modbuscrchex"
- CRC8
let data = "5A A5 01 00 26 00 D2 BB B6 FE C8 FD CB C4 CE E5 C1 F9 C6 DF B0 CB BE C5 CA AE 31 32 33 34 35 36 37 38 39 31 32 33 34 35 36 37 38 39"
// 去掉十六进制的空格
let hex = data.replace(/\s+/g, "")
// 转换的十六进制数组
let array = HexUtils.hexToArray(hex)
let params = {
data: array, // 数据
mode: "CRC8_TYPE_defaultCrc" // 校验算法,参考下面说明
}
let result = CRCUtils.getCRC8(params)
mode(crc校验算法)取之类型有:
-
CRC8_TYPE_defaultCrc
-
CRC8_TYPE_cdma2000
-
CRC8_TYPE_darc
-
CRC8_TYPE_dvbS2
-
CRC8_TYPE_ebu
-
CRC8_TYPE_iCode
-
CRC8_TYPE_itu
-
CRC8_TYPE_maxim
-
CRC8_TYPE_rohc
-
CRC8_TYPE_wcdma
-
CRC16
let data = "5A A5 01 00 26 00 D2 BB B6 FE C8 FD CB C4 CE E5 C1 F9 C6 DF B0 CB BE C5 CA AE 31 32 33 34 35 36 37 38 39 31 32 33 34 35 36 37 38 39"
// 去掉十六进制的空格
let hex = data.replace(/\s+/g, "")
// 转换的十六进制数组
let array = HexUtils.hexToArray(hex)
let params = {
data: array, // 数据
mode: "CRC16_TYPE_modbus" // 校验算法,参考下面说明
}
let result = CRCUtils.getCRC16(params)
// result:{"crc":35917,"low":77,"high":140,"hex":"8C4D"}
mode(crc校验算法)取之类型有:
-
CRC16_TYPE_ccittFalse
-
CRC16_TYPE_arc
-
CRC16_TYPE_augCcitt
-
CRC16_TYPE_buypass
-
CRC16_TYPE_cdma2000
-
CRC16_TYPE_dds110
-
CRC16_TYPE_dectR
-
CRC16_TYPE_dectX
-
CRC16_TYPE_dnp
-
CRC16_TYPE_en13757
-
CRC16_TYPE_genibus
-
CRC16_TYPE_maxim
-
CRC16_TYPE_mcrf4xx
-
CRC16_TYPE_riello
-
CRC16_TYPE_t10dif
-
CRC16_TYPE_teledisk
-
CRC16_TYPE_tms37157
-
CRC16_TYPE_usb
-
CRC16_TYPE_a
-
CRC16_TYPE_kermit
-
CRC16_TYPE_modbus
-
CRC16_TYPE_x25
-
CRC16_TYPE_xmodem
-
CRC32 CRC32在浏览器上有值溢出问题,暂时不支持浏览器
let data = "5A A5 01 00 26 00 D2 BB B6 FE C8 FD CB C4 CE E5 C1 F9 C6 DF B0 CB BE C5 CA AE 31 32 33 34 35 36 37 38 39 31 32 33 34 35 36 37 38 39"
// 去掉十六进制的空格
let hex = data.replace(/\s+/g, "")
// 转换的十六进制数组
let array = HexUtils.hexToArray(hex)
let params = {
data: array, // 数据
mode: "CRC32_TYPE_defaultCrc" // 校验算法,参考下面说明
}
let result = CRCUtils.getCRC32(params)
mode(crc校验算法)取之类型有:
- CRC32_TYPE_defaultCrc
- CRC32_TYPE_bzip2
- CRC32_TYPE_c
- CRC32_TYPE_d
- CRC32_TYPE_mpeg2
- CRC32_TYPE_posix
- CRC32_TYPE_sata
- CRC32_TYPE_q
- CRC32_TYPE_jamcrc
- CRC32_TYPE_xfer
modbus
import {
HexUtils, ModbusUtils
} from "@/uni_modules/wrs-uts-modbuscrchex"
- 读数据指令
// 设备地址
let address = 0x25;
// 寄存器起始地址
let start = 20;
// 寄存器个数
let count = 3;
// crc校验类型,参考CRC16接口的mode字段
let crcMode = "CRC16_TYPE_modbus"
// CRC校验是否低位在前
let crcLowFront = false
let byteArray = ModbusUtils.getModbusReadData(address, start, count, crcMode, crcLowFront);
let hex = HexUtils.arrayToHex(byteArray);
- 写数据指令
// 设备地址
let address = 0x25;
// 寄存器起始地址
let start = 20;
// 数据
let data = [];
data.push(0x02);
data.push(0x0A);
// crc校验类型
let crcMode = "CRC16_TYPE_modbus"
// CRC校验是否低位在前
let crcLowFront = false
let byteArray = ModbusUtils.getModbusWriteData(address, start, data, crcMode, crcLowFront);
let hex = HexUtils.arrayToHex(byteArray);
制转转换
import {
DecimalUtils
} from "@/uni_modules/wrs-uts-modbuscrchex"
- 二进制转十进制
let bitStr = "11101"
let result = DecimalUtils.bitToDec(bitStr)
// bitToDec bit:11101 value:29
- 十进制转二进制
let result = 29
let bitStr = DecimalUtils.decToBit(result)
// decToBit dec:29 value:11101
- 十六进制转十进制
let hexStr = "00FF"
let result = DecimalUtils.hexToDec(hexStr)
// hexToDec hex:00FF value:255
- 十进制转十六进制
let result = 255
let hexStr = DecimalUtils.decToHex(result)
整型工具类
import {
IntUtils
} from "@/uni_modules/wrs-uts-modbuscrchex"
- 高低位转整型
let low = 226;
// 高位
let high = 102;
// 26338
let value = IntUtils.highLowToInt(high,
low)
- 整型转高低位
let value = 26338;
// 26338
let obj = IntUtils.intToHighLow(value)
// 低位
let low = obj.low;
// 高位
let high = obj.high;
- 大端序-字节数组转整型
var byteArray = [0x01, 0x02, 0x03, 0x04]
var intValue = IntUtils.bigEndianToInt(byteArray)
- 大端序-整型转字节数组
var intValue = 2461;
var byteArray = IntUtils.bigEndianToByteArray(intValue)
- 小端序-字节数组转整型
var byteArray = [0x01, 0x02, 0x03, 0x04]
var intValue = IntUtils.littleEndianToInt(byteArray)
- 小端序-整型转字节数组
var intValue = 2461;
var byteArray = IntUtils.littleEndianToByteArray(intValue)
文件工具类
import {
FileUtils, HexUtils
} from "@/uni_modules/wrs-uts-modbuscrchex"
- 获取文件字节数据
// 绝对路径
let path = plus.io.convertLocalFileSystemURL("_www/static/logo.png")
FileUtils.getFileData(path, (array)=>{
let hex = HexUtils.arrayToHex(array);
let msg = "getFileData:" + hex;
this.showMsg(msg)
})
沾包粘包
粘包问题是指当发送两条消息时,比如发送了 ABC 和 DEF,但另一端接收到2条数据,第1条是 ABCD,第2条是EF,像这种一次性读取了两条数据的情况就叫做粘包(正常情况应该是一条一条读取的)。
当发送的消息是 ABC 时,另一端却接收到的是 AB 和 C 两条信息,像这种情况就叫做半包
针对这种问题的解决方案有:
-
封装协议请求 数据封装为两部分:数据头+数据正文,在数据头中存储数据正文的大小,当读取的数据小于数据头中的大小时,继续读取数据,直到读取的数据长度等于数据头中的长度时才停止。
-
用特殊字符作为每条指令的头尾 数据封装为两部分:帧头+数据正文(如果包含帧头/帧尾的数据需要转义)+帧尾,接收端收到数据先缓存起来,再按照特殊字符拆分每条指令
SLIP协议
SLIP提供了两个特殊字符,END(0xC0)和 ESC(0xDB),SLIP报文的头尾都有一个END字符
转义部分:
若报文中某个字符为END,那么就连续传输两个字节0xDB和0xDC来取代; 若报文中某个字符为ESC,那么就连续传输两个字节0xDB和0xDD来取代;
接口:
import {
SLIPUtils, HexUtils
} from "@/uni_modules/wrs-uts-modbuscrchex"
- 封装发送数据
let array = [0x00, 0xFF, 0xEE]
let hexArray = SLIPUtils.getSLIP(array)
// send hexArray,实际发送的是hexArray
// 如果是蓝牙有mtu限制的话,请将hexArray按照mtu大小拆分成n段发送,上一段发送成功后再发送下一段
- 接收数据
let array = [0xC0, 0xAA, 0xC0, 0xC0, 0x11]
// 接收到数据,往数据缓存里面添加即可,如果缓存到有符合格式的数据时,会自动通过slip.setCallback回调识别到的单条指令
slip.addReceiveData(array)
- 设置接收数据解析完完整数据时的回调
slip.setCallback((oneOrderArray)=>{
// oneOrderArray时发送端发送的一条完整数据
let hex = HexUtils.arrayToHex(oneOrderArray);
this.showMsg('接收到数据为 十六进制数组:' + oneOrderArray + " 十六进制字符串:" + hex)
})