//build: 20240715
|
//数据通信通道,包括串口(Serial port)、USB(Universal Serial Bus)和韦根(Wiegand)
|
//依赖组件:dxDriver,dxStd,dxLogger,dxMap,dxEventBus,dxCommon
|
import { channelClass } from './libvbar-m-dxchannel.so'
|
import std from './dxStd.js'
|
import dxMap from './dxMap.js'
|
import dxCommon from './dxCommon.js'
|
import bus from './dxEventBus.js'
|
const uartObj = new channelClass();
|
const map = dxMap.get('default')
|
const uart = {}
|
uart.TYPE = {
|
USBKBW: 1,//USB Keyboard Wedge通过USB接口连接键盘,并以韦根协议的形式传输数据
|
USBHID: 2,//USB人体接口设备(USB Human Interface Device)通道类型
|
UART: 3,//表示UART通道类型,即串口通道
|
WIEGAND: 4//韦根(Wiegand)通道类型
|
}
|
|
/* 各类通道 IO 控制操作的设置选项枚举 */
|
uart.IOC_SET_CMD = {
|
/* 设置KBW通道的配置参数 */
|
CHANNEL_IOC_SET_KBW_CONFIG : 1,
|
/* 设置KBW通道的上位机参数 */
|
CHANNEL_IOC_SET_KBW_UPPER : 2,
|
/* KBW上线时间 */
|
CHANNEL_IOC_SET_KBW_UPTIME : 3,
|
/* KBW下线时间 */
|
CHANNEL_IOC_SET_KBW_DOWNTIME : 4,
|
/* 设置HID通道的报告长度 */
|
CHANNEL_IOC_SET_HID_REPORT_LEN : 5,
|
/* 设置UART通道的参数 */
|
CHANNEL_IOC_SET_UART_PARAM : 6,
|
/* 设置韦根通道的工作模式 */
|
CHANNEL_IOC_SET_WIEGAND_MODE : 7,
|
/* 设置韦根通道的GPIO配置 */
|
CHANNEL_IOC_SET_WIEGAND_GPIO : 8,
|
/* 设置韦根通道的延迟时间 */
|
CHANNEL_IOC_SET_WIEGAND_DELAY : 9,
|
/* 设置韦根通道的日志记录功能 */
|
CHANNEL_IOC_SET_WIEGAND_LOG : 10
|
|
};
|
|
/* 韦根通道的不同工作模式 */
|
uart.WIEGAND_MODE = {
|
/* 韦根模式初始化值 */
|
WIEGAND_MODE_INIT : 0,
|
/* 韦根 26 位模式 */
|
WIEGAND_MODE_26 : 1,
|
/* 韦根 34 位模式 */
|
WIEGAND_MODE_34 : 2,
|
/* 韦根 128 位模式 */
|
WIEGAND_MODE_128 : 3,
|
/* 韦根 256 位模式 */
|
WIEGAND_MODE_256 : 4,
|
/* 韦根 2048 位模式 */
|
WIEGAND_MODE_2048 : 5,
|
/* 自定义的韦根模式, 最大发送 6400 位 */
|
WIEGAND_MODE_CUSTOM : 6
|
};
|
|
/**
|
* 打开信道
|
* @param {number} type 通道类型,参考枚举 TYPE,必填
|
* @param {string} path 不同的设备或同一设备的不同类型通道对应的path不一样,比如DW200的485对应的值是"/dev/ttyS2",必填
|
* @param {string} id 句柄id,非必填(若打开多个实例需要传入唯一id)
|
*/
|
uart.open = function (type, path, id) {
|
if (type === undefined || type === null) {
|
throw new Error("uart.open:'type' should not be null or empty")
|
}
|
if (path === undefined || path === null) {
|
throw new Error("uart.open:'path' should not be null or empty")
|
}
|
|
let pointer = uartObj.open(type, path);
|
|
if (pointer === undefined || pointer === null) {
|
throw new Error("uart.open: open failed")
|
}
|
|
dxCommon.handleId("uart", id, pointer)
|
}
|
|
/**
|
* 信道数据发送
|
* @param {ArrayBuffer} buffer 要发送的数据,必填
|
* @param {string} id 句柄id,非必填(需保持和init中的id一致)
|
* @returns true/false
|
*/
|
uart.send = function (buffer, id) {
|
if (buffer === undefined || buffer === null) {
|
throw new Error("uart.send: 'buffer' should not be null or empty")
|
}
|
let pointer = dxCommon.handleId("uart", id)
|
|
return uartObj.send(pointer, buffer);
|
}
|
|
/**
|
* 信道数据发送,使用微光通信协议格式
|
* @param {string/object} data 要发送的数据,必填
|
* @param {string} id 句柄id,非必填(需保持和init中的id一致)
|
* @returns true/false
|
*/
|
uart.sendVg = function (data, id) {
|
if (!data) {
|
return
|
}
|
if (typeof data === 'string') {
|
uart.send(dxCommon.hexStringToArrayBuffer(data), id)
|
return
|
}
|
let pack = '55aa' + data.cmd
|
if (data.hasOwnProperty('result')) {
|
pack += data.result
|
}
|
pack += (data.length % 256).toString(16).padStart(2, '0')
|
pack += (Math.floor(data.length / 256)).toString(16).padStart(2, '0')
|
pack += data.data
|
let all = dxCommon.hexToArr(pack)
|
let bcc = dxCommon.calculateBcc(all)
|
all.push(bcc)
|
uart.send(new Uint8Array(all).buffer, id)
|
}
|
|
/**
|
* 接收数据,需要在线程里轮询去获取,返回Uint8Array类型
|
* 如果接收到的数据没有达到size长度,会继续等待直到接收到size长度,但是如果timeout很短,就会有可能没收完就结束这一次操作
|
* @param {number} size 接收数据的字节数,必填
|
* @param {number} timeout 超时时间(毫秒)这个函数会阻塞等待最多这个时间就结束,如果提前接收到了size个数据也会结束,非必填,缺省是10ms
|
* @param {string} id 句柄id,非必填(需保持和init中的id一致)
|
* @returns Uint8Array,返回值的byteLength表示接收到的长度,如果为0表示没有接收到任何数据
|
*/
|
uart.receive = function (size, timeout, id) {
|
if (size === undefined || size === null) {
|
throw new Error("uart.receive:'size' should not be null or empty")
|
}
|
|
if (timeout === undefined || timeout === null) {
|
timeout = 10
|
}
|
|
let pointer = dxCommon.handleId("uart", id)
|
|
let res = uartObj.receive(pointer, size, timeout)
|
if (res === null) {
|
return null
|
}
|
return new Uint8Array(res)
|
}
|
|
/**
|
* 调用信道特殊IO接口
|
* @param {*} request
|
* @param {*} arg
|
* @param {string} id 句柄id,非必填(需保持和init中的id一致)
|
* @returns true/false
|
*/
|
uart.ioctl = function (request, arg, id) {
|
let pointer = dxCommon.handleId("uart", id)
|
|
return uartObj.ioctl(pointer, request, arg)
|
}
|
|
/**
|
* 关闭信道
|
* @param {string} id 句柄id,非必填(需保持和init中的id一致)
|
* @returns true/false
|
*/
|
uart.close = function (id) {
|
let pointer = dxCommon.handleId("uart", id)
|
|
return uartObj.close(pointer)
|
}
|
|
|
/**
|
* 刷新信道
|
* @param {number} queue_selector 必填
|
* @param {string} id 句柄id,非必填(需保持和init中的id一致)
|
* @returns true/false
|
*/
|
uart.flush = function (queue_selector, id) {
|
if (queue_selector == null) {
|
throw new Error("queue_selector should not be null or empty")
|
}
|
let pointer = dxCommon.handleId("uart", id)
|
|
return uartObj.flush(pointer, queue_selector);
|
}
|
|
|
uart.VG = {
|
RECEIVE_MSG: '__uartvg__MsgReceive',
|
}
|
|
/**
|
* 简化微光通信协议的使用,
|
* 1. 接受数据:把TLV的二进制的数据接受到后解析成对象,并以eventbus的event发送出去(uart.VG.RECEIVE_MSG+options.id)
|
* 返回的对象格式:{cmd:"2a",result:"01",length:7,data:"0a1acc320fee32",bcc:true}
|
* cmd: 1个字节的命令字,16进制字符串
|
* result:1个字节的标识字,表示数据处理的结果,成功或失败或其他状态。只有反馈数据才有标识字,16进制字符串
|
* length:数据的长度,在TLV里用2个字节来定义,这里直接转成10进制的数字
|
* data:多个字节的数据域,16进制字符串
|
* bcc: bcc校验成功或失败
|
* 2. 发送数据:把对象转成TLV格式的二进制数据再发送出去,可以通过uart.sendVg('要发送的数据',id),数据格式如下
|
* 发送的数据格式有二种 1.对象格式 :{cmd:"2a",result:"01",length:7,data:"0a1acc320fee32"} 2. 完整的16进制字符串'55AA09000000F6'
|
* 3. 同样的id,多次调用runvg也只会执行一次
|
*
|
* @param {object} options 启动的参数
|
* @param {number} options.type 通道类型,参考枚举 TYPE,必填 (兼容USBHID块传输,默认1024每块)
|
* @param {string} options.path 不同的设备或同一设备的不同类型通道对应的path不一样,比如DW200的485对应的值是"/dev/ttyS2",必填
|
* @param {number} options.result 0和1(缺省是0),标识是接收的数据还是发送的数据包含标识字节,0表示接受的数据不包括标识字,发送的数据包括,1是反之
|
* @param {number} options.passThrough passThrough为true则接收的数据使用透传模式,非必填
|
* @param {string} options.id 句柄id,非必填(若初始化多个实例需要传入唯一id)
|
*/
|
uart.runvg = function (options) {
|
if (options === undefined || options.length === 0) {
|
throw new Error("dxuart.runvg:'options' parameter should not be null or empty")
|
}
|
if (options.id === undefined || options.id === null || typeof options.id !== 'string') {
|
// 句柄id
|
options.id = ""
|
}
|
if (options.type === undefined || options.type === null) {
|
throw new Error("dxuart.runvg:'type' should not be null or empty")
|
}
|
if (options.path === undefined || options.path === null) {
|
throw new Error("dxuart.runvg:'path' should not be null or empty")
|
}
|
let oldfilepre = '/app/code/dxmodules/vgUartWorker'
|
let content = std.loadFile(oldfilepre + '.js').replace("{{id}}", options.id)
|
let newfile = oldfilepre + options.id + '.js'
|
std.saveFile(newfile, content)
|
let init = map.get("__vguart__run_init" + options.id)
|
if (!init) {//确保只初始化一次
|
map.put("__vguart__run_init" + options.id, options)
|
bus.newWorker(options.id || "__uart",newfile)
|
}
|
}
|
export default uart;
|