Authored by Rock Zhang

Merge remote-tracking branch 'origin/master'

Conflicts:
	.gitignore
	package.json
	src/index.js
	src/lib/directive/inventory.js
{
"browser": true,
"devel": true,
"esnext": true,
"indent": 2,
"jquery": false,
"maxlen": 80,
"node": true
}
\ No newline at end of file
... ...
读写器的SDK
------------
问题:
本SDK主要用于UHF RFID读写器的调用。完全用node来实现Socket的硬件通讯。
已实现接口:
* 打开读写器(A0 00 00 00 00)
* 关闭读写器(A1 00 00 00 00)
* 设置功率(F3 10 00 00 00)
* 设置定频(BF 00 00 00 00)
* 获取配置(B3 00 00 00 00)
* 开始盘点(F1 00 00 00 00)
* 结束盘点(F2 00 00 00 00)
* 获取固件版本(B4 00 00 00 00)
* 设置盘点时长(B0 00 00 00 00)
类关联图
```
index + config
入口 配置
|
directive\Base--> Util + Connector + interface
指令基类 工具类 连接器类<多例> 接口标准输入,输出
|
-----------------------------------------
| | |
directive\Uhf directive\Config directive\Inventory
UHF模块指令类 配置指令类 盘点指令类
```
使用方法
==============
### 环境准备
#### 安装nodejs最新版(0.12.2以上)
[下载](https://nodejs.org/download/)
#### 安装gulp
```
npm install gulp -g -d
```
### 下载和部署rfid-sdk
```
git clone git@git.dev.yoho.cn:web/rfid-sdk.git
cd rfid-sdk
npm install
```
es5调用方法
``` javascript
//调用
var sdk = require('../dist/index');//模块入口
```
es6调用方法
```
//调用
require("babel/register");//需要加入Babel的polyfill
var sdk = require('../src/index');//模块入口
```
``` javascript
//开始盘点
sdk.start({
host: '172.16.13.6', //IP
port: '9761', //端口
filter: { //设置灵敏度的过滤
'on': '1',
rssi: -60
},
frequencys: [{ //天线的定频
ant: 0,
freq: 10
}, {
ant: 1,
freq: 10
}, {
ant: 2,
freq: 10
}, {
ant: 3,
freq: 10
}],
inventoryTime: 400, //设置盘点时长
power: [15, 0, 0, 0] //功率设置
}, function (data) {
console.log(data);
});
```
## 问题:
1.对于多个返回结果的拆分(已解决)
2.设置定频,没有起作用
\ No newline at end of file
2.设置定频,没有起作用(待验证)
3.socket连接异常处理
\ No newline at end of file
... ...
var gulp = require('gulp');
var fs = require('fs');
var exec = require('child_process').exec;
var jshint = require('gulp-jshint');
var stylish = require('jshint-stylish');
var babel = require('gulp-babel');
var gulpDoxx = require('gulp-doxx');
var path = require('path');
gulp.task('default', ['hint', 'babel', 'doc'], function () {
console.log('DONE!');
});
//ES6转ES5
gulp.task('babel', function () {
return gulp.src('src/**/*.js')
.pipe(babel())
.pipe(gulp.dest('dist'));
});
//转文档
gulp.task('doc', function () {
gulp.src(['src/**/*.js', 'README.md'])
.pipe(gulpDoxx({
title: 'JW UHF node client SDK',
urlPrefix: path.join(__dirname, "docs")
}))
.pipe(gulp.dest('docs'))
});
//js代码验证
gulp.task('hint', function () {
return gulp.src(['src/**/*.js'])
.pipe(jshint())
.pipe(jshint.reporter(stylish));
});
\ No newline at end of file
... ...
/**
* 配置
* @fileOverview 配置
* @module config
* @property {string} log 日志的记录路径
* @property {string} logLevel 日志级别
* @property {number} checkInventory 检查盘点标签的状态
* @property {number} offInventory 离线标签临界点
* @property {number} checkCount 读取数检查
*/
export default {
log: './log',
... ...
/**
* @fileOverview 读写器连接客户端连接器类
* @author qiqi.zhou@yoho.cn
*/
import net from 'net';
import orders from './interface';
import events from 'events';
... ... @@ -7,11 +11,22 @@ import {
from './util';
/**
* 连接器
* 连接到读写器端
* @class 连接器
* @extends {EventEmitter}
* @module Connector
* @member {Socket} client
* @member {Array} orderMq
* @description 连接到读写器端
*/
class Connector extends events.EventEmitter {
/**
* socket 客户端初始化
* @param {Object} config 配置
* @param {Function} send 发送的回调
* @param {Function} receive 接收的回调
* @return {void} 无返回
*/
constructor(config, send, receive) {
super();
this.orderMq = [];
... ... @@ -60,4 +75,8 @@ class Connector extends events.EventEmitter {
this.client.write(call);
}
}
/**
* @exports lib/Connector
*/
export default Connector;
\ No newline at end of file
... ...
/**
* @fileOverview 读写器指令模块基类
* @author qiqi.zhou@yoho.cn
*/
import _ from 'lodash';
import orders from '../interface';
import {
... ... @@ -8,16 +12,28 @@ from '../util';
/**
* 读写器的指令操作基类
* @class 读写器的指令操作基类
* @module lib/directive/Base
* @member {Object} reproc 预处理方法
* @member {object} proc 返回结果处理
*/
class Base {
/**
* 构造函数
* @return {void}
*/
constructor() {
this.reproc = {};
this.proc = {};
}
/**
* 发送读写器模块指令
* @method send
* @description 发送读写器模块指令
* @param {Connector} connector 链接器socket客户端
* @param {Object} order 指令
* @param {Object} param 传参
* @return {void} 无返回
*/
send(connector, order, param) {
let sendOrder = order.input;
... ... @@ -30,7 +46,11 @@ class Base {
}
/**
* 接收读写器模块
* @method receive
* @description 接收读写器模块
* @param {client} client socket客户端
* @param {Array} data 接收指令
* @return {Object} 标准输出
*/
receive(client, data) {
let procFunc = this.procFunc,
... ... @@ -44,7 +64,7 @@ class Base {
log.info('读写器(' + client.remoteAddress + ')接收指令:' + data.join(' '));
//读取命令配置
order = locateOrder(orders, data)
order = locateOrder(orders, data);
if (order.name) {
if (this.proc[order.name]) {
... ... @@ -57,11 +77,19 @@ class Base {
}
/**
* 处理返回结果
* @method procFunc
* @description 处理返回结果
* @param {Array} data 返回的结果数组
* @param {Socket} client socket客户端
* @param {String} method 方法名
* @return {Object} 标准输出
*/
procFunc(data, client, method) {
return returnProc(data, client.remoteAddress, orders[method].output);
}
}
/**
* @exports lib/directive/Base
*/
export default Base;
\ No newline at end of file
... ...
/**
* @fileOverview 读写器配置类
* @author qiqi.zhou@yoho.cn
*/
import Base from './base';
import _ from 'lodash';
import {
... ... @@ -7,10 +11,17 @@ from '../util';
import info from '../interface';
/**
* 配置读写器信息
* 频率,功率,灵敏度过滤
* @class 配置读写器信息
* @description 频率,功率,灵敏度过滤
* @module lib/directive/Config
* @extends {Base}
* @member @see {@link Base}
*/
class Config extends Base {
/**
* 初始化和配置输入处理
* @return {void}
*/
constructor() {
super(null);
... ... @@ -24,9 +35,10 @@ class Config extends Base {
}
/**
* 设置功率输入预处理
* param: [15,15,0,0]
* 分别对应0-3天线
* @method prePower
* @description 设置功率输入预处理
* @param {Array} param 天线功率,eg.[15,15,0,0]分别对应0-3天线
* @return {String} 指令
*/
prePower(param) {
let ret = [];
... ... @@ -41,16 +53,19 @@ class Config extends Base {
}
/**
* 设置灵敏度过滤预处理
* param:{on:'1',rssi:-275}
* @method preFilter
* @description 设置灵敏度过滤预处理
* @param {Object} param 配置1表示开启,0表示关闭,eg. {on:'1',rssi:-27.5}
*/
preFilter(param) {
let rssi = tenToHex(param.rssi).replace('ffff', '').toLocaleUpperCase();
let rssi = tenToHex(param.rssi * 10);
rssi = rssi.replace('ffff', '').toLocaleUpperCase();
return info.setFilter.input + '0' + param.on + rssi + '00';
}
/**
* 设置频率预处理
* @method preFrequency
* @description 设置频率预处理
0 915.75
1 915.25
2 903.25
... ... @@ -101,8 +116,7 @@ class Config extends Base {
47 922.75
48 902.75
49 923.25
* ant:1
* freq:1
* @param {Number} param ant标示天线的端口,freq标示频率(使用枚举值)
*/
preFrequency(param) {
let ant = param.ant < 10 ? ('0' + param.ant) : param.ant,
... ... @@ -111,4 +125,7 @@ class Config extends Base {
return info.setFrequency.input + ant + '0000' + freq;
}
}
/**
* @exports lib/directive/Config
*/
export default Config;
\ No newline at end of file
... ...
/**
* @fileOverview 读写器模块类
* @author qiqi.zhou@yoho.cn
*/
import Base from './base';
import _ from 'lodash';
import {
... ... @@ -7,7 +11,9 @@ from '../util';
import info from '../interface';
/**
* UHF 读写器的指令操作上
* @class UHF 读写器的指令操作上
* @extends {Base}
* @member @see {@link Base}
*/
class Uhf extends Base {
constructor() {
... ... @@ -19,14 +25,20 @@ class Uhf extends Base {
}
/**
* 获取读写器信息返回处理
* @method getConfig
* @description 获取读写器信息返回处理
* @param {Array} data 返回的指令数组
* @param {Socket} client socket客户端
* @return {Object} 标准输出
*/
getConfig(data, client) {
let region = ['FCC', 'CCC', 'NCC', 'JPN'],
power = [],
retData = {},
retKey = null,
returnVal = null;
returnVal = null,
ip,
output;
for (let val of _.slice(data, 2, 4)) {
power.push(parseInt(val, 16));
... ... @@ -39,25 +51,32 @@ class Uhf extends Base {
speedMode: Number(data[7]),
invTime: parseInt(_.slice(data, 8, 12).join(''), 16),
invCount: data[12]
}
};
retKey = _.slice(data, 0, 2);
} else {
retKey = data;
}
returnVal = returnProc(retKey, client.remoteAddress, info.getConfig.output);
ip = client.remoteAddress;
output = info.getConfig.output;
returnVal = returnProc(retKey, ip, output);
returnVal.data = retData;
return returnVal;
}
/**
* 获取版本返回处理
* @method getVersion
* @description 获取版本返回处理
* @param {Array} data 返回指令数组
* @param {Socket} client socket连接客户端
* @return {Object} 标准输出
*/
getVersion(data, client) {
let retData = null;
let retKey = _.slice(data, 0, 4);
let returnVal = returnProc(retKey, client.remoteAddress, info.getVersion.output);
let retData = null,
retKey = _.slice(data, 0, 4),
ip = client.remoteAddress,
output = info.getVersion.output;
let returnVal = returnProc(retKey, ip, output);
if (data[2] === '0' && data[3] === '0') {
returnVal.data = {
majorVersion: parseInt(data[4], 16),
... ... @@ -68,4 +87,8 @@ class Uhf extends Base {
return returnVal;
}
}
/**
* @exports lib/directive/Uhf
*/
export default Uhf;
\ No newline at end of file
... ...
/**
* 通用返回信息
* @fileOverview 指令配置文件
* @author qiqi.zhou@yoho.cn
* @module interface
*/
/**
* @var {Object} 通用返回信息
*/
var commonMessage = {
'00': {
... ... @@ -18,10 +24,11 @@ var commonMessage = {
code: -1,
message: '操作失败'
}
}
};
/**
* 指令集枚举
* @exports default
*/
export default {
openUhf: {
... ... @@ -29,7 +36,7 @@ export default {
input: 'A000000000',
output: {
'a0200': commonMessage['00'],
'a02ff0': commonMessage['ff0'],
'a02ff0': commonMessage.ff0,
'a02f00': {
code: 2,
message: 'UHF模块已打开'
... ... @@ -41,7 +48,7 @@ export default {
input: 'A100000000',
output: {
'a1200': commonMessage['00'],
'a12ff0': commonMessage['ff0']
'a12ff0': commonMessage.ff0
}
},
setPower: {
... ... @@ -49,9 +56,9 @@ export default {
input: 'F3',
output: {
'f3200': commonMessage['00'],
'f32ffff': commonMessage['ffff'],
'f32fffe': commonMessage['fffe'],
'f32ff0': commonMessage['ff0']
'f32ffff': commonMessage.ffff,
'f32fffe': commonMessage.fffe,
'f32ff0': commonMessage.ff0
}
},
setFilter: {
... ... @@ -59,9 +66,9 @@ export default {
input: 'B7',
output: {
'b7200': commonMessage['00'],
'b72ffff': commonMessage['ffff'],
'b72fffe': commonMessage['fffe'],
'b72ff0': commonMessage['ff0']
'b72ffff': commonMessage.ffff,
'b72fffe': commonMessage.fffe,
'b72ff0': commonMessage.ff0
}
},
setFrequency: {
... ... @@ -69,9 +76,9 @@ export default {
input: 'BF',
output: {
'bf200': commonMessage['00'],
'bf2ffff': commonMessage['ffff'],
'bf2fffe': commonMessage['fffe'],
'bf2ff0': commonMessage['ff0']
'bf2ffff': commonMessage.ffff,
'bf2fffe': commonMessage.fffe,
'bf2ff0': commonMessage.ff0
}
},
getConfig: {
... ... @@ -79,8 +86,8 @@ export default {
input: 'B300000000',
output: {
'b3200': commonMessage['00'],
'b32ffff': commonMessage['ffff'],
'b32fffe': commonMessage['fffe'],
'b32ffff': commonMessage.ffff,
'b32fffe': commonMessage.fffe,
'b316': {
code: 1,
message: '返回信息'
... ... @@ -92,9 +99,9 @@ export default {
input: 'B400000000',
output: {
'b4400': commonMessage['00'],
'b44ffff': commonMessage['ffff'],
'b44fffe': commonMessage['fffe'],
'b44ff0': commonMessage['ff0']
'b44ffff': commonMessage.ffff,
'b44fffe': commonMessage.fffe,
'b44ff0': commonMessage.ff0
}
},
sartInventory: {
... ... @@ -102,8 +109,8 @@ export default {
input: 'F100000000',
output: {
'f1200': commonMessage['00'],
'f12ffff': commonMessage['ffff'],
'f12fffe': commonMessage['fffe'],
'f12ffff': commonMessage.ffff,
'f12fffe': commonMessage.fffe,
'f1': {
code: 2,
message: '返回信息'
... ... @@ -120,9 +127,9 @@ export default {
input: 'F200000000',
output: {
'f2200': commonMessage['00'],
'f22ffff': commonMessage['ffff'],
'f22fffe': commonMessage['fffe'],
'f22ff0': commonMessage['ff0']
'f22ffff': commonMessage.ffff,
'f22fffe': commonMessage.fffe,
'f22ff0': commonMessage.ff0
}
},
setInventoryTime: {
... ... @@ -130,9 +137,9 @@ export default {
input: 'B0',
output: {
'b0200': commonMessage['00'],
'b02ffff': commonMessage['ffff'],
'b02fffe': commonMessage['fffe'],
'b02ff0': commonMessage['ff0']
'b02ffff': commonMessage.ffff,
'b02fffe': commonMessage.fffe,
'b02ff0': commonMessage.ff0
}
}
};
\ No newline at end of file
... ...
/**
* 工具方法库
* @fileOverview 工具方法库
* @module lib/util
* @author qiqi.zhou@yoho.cn
*/
import config from '../config';
... ... @@ -13,19 +15,27 @@ let loger = log4js.getLogger('log');
loger.setLevel(config.logLevel); //配置日志
/**
* 日志
* @mixes 日志记录对象
* @exports util/log
*/
export let log = loger;
/**
* 无符号转16进制
* @method 无符号转16进制
* @exports util/tenToHex
* @param {Number} number 十进制数
* @return {Number} 16进制数字
*/
export let tenToHex = function (number) {
return (parseInt(number, 10) >>> 0).toString(16);
}
};
/**
* 无符号16进制转10进制
* @method 无符号16进制转10进制
* @exports util/hexToTen
* @param {Number} number 十六机制数
* @param {Boolean} minus true表示负数,false表示正数
* @return {Number} 十进制数字
*/
export let hexToTen = function (number, minus) {
if (minus) {
... ... @@ -34,10 +44,13 @@ export let hexToTen = function (number, minus) {
return parseInt(number, 16);
}
}
};
/**
* 转16进制
* @method 转16进制
* @exports util/toHex
* @param {Buff} data 返回数据流
* @return {Array} 转成16进制的数组
*/
export let toHex = function (data) {
let arr = [];
... ... @@ -49,7 +62,12 @@ export let toHex = function (data) {
/**
* 处理返回码
* @method 处理返回码
* @exports util/returnProc
* @param {Array} data 指令结果
* @param {Array} ip 读写器IP
* @param {Object} output 标准输出的规格对象
* @return {object} 标准输出
*/
export let returnProc = function (data, ip, output) {
if (!_.isArray(data) || _.size(data) < 1) {
... ... @@ -63,10 +81,14 @@ export let returnProc = function (data, ip, output) {
log.info("读写器(" + ip + ")返回:" + output[ret].message + " 返回码:" + ret);
output[ret].hex = data;
return output[ret];
}
};
/**
* 返回结果拆分
* @method 返回结果拆分
* @exports util/spliteRet
* @param {Array} mq 发起指令的数组集合
* @param {String} data 得到的指令数据结果集
* @return {Object} 返回拆分结果和拆分依据的指令头
*/
export let spliteRet = function (mq, data) {
let indexes = [],
... ... @@ -76,7 +98,7 @@ export let spliteRet = function (mq, data) {
j,
leftMq = [],
prevIndex = -1;
for (i = 0; i < mq.length; i++) {
for (i = 0; i < mq.length; i++) { //按照顺序获取所有的指令的第一位标示位置
prevIndex = _.indexOf(data, mq[i], prevIndex + 1);
if (prevIndex < 0) {
leftMq = mq.slice(i);
... ... @@ -84,7 +106,7 @@ export let spliteRet = function (mq, data) {
}
indexes.push(prevIndex);
}
for (k = 0; k < indexes.length; k++) {
for (k = 0; k < indexes.length; k++) { //拆分结果集
if (indexes[k + 1]) {
rets.push(data.slice(indexes[k], indexes[k + 1]));
} else {
... ... @@ -92,13 +114,13 @@ export let spliteRet = function (mq, data) {
break;
}
}
if (indexes.length < 2) {
if (indexes.length < 2) { //如果是拆分点小于2的,直接返回结果集
rets = [data];
}
let allRets = [];
for (j = 0; j < rets.length; j++) {
if (rets[j][0] == 'f1' || rets[j][1] != '2') { //盘点特殊处理
if (rets[j][0] == 'f1' || rets[j][1] != '2') { //对于盘点一次指令,多次返回,盘点特殊处理
let length = hexToTen(rets[j][1]);
let allLength = rets[j].length;
... ... @@ -116,10 +138,14 @@ export let spliteRet = function (mq, data) {
rets: allRets,
mq: leftMq,
};
}
};
/**
* 定位指令名称
* @method 定位指令名称
* @exports util/spliteRet
* @param {Array} orders 指令规格数组
* @param {Array} data 返回的结果集 eg. ['f0','2','0','0']
* @return {Object} 返回定位到的指令
*/
export let locateOrder = function (orders, data) {
let orderRet = {};
... ... @@ -133,4 +159,4 @@ export let locateOrder = function (orders, data) {
}
});
return orderRet;
}
\ No newline at end of file
};
\ No newline at end of file
... ...
//调用
var sdk = require('../dist/index');
//开始盘点
sdk.start({
host: '172.16.13.6', //IP
port: '9761', //端口
filter: { //设置灵敏度的过滤
'on': '1',
rssi: -60
},
frequencys: [{ //天线的定频
ant: 0,
freq: 10
}, {
ant: 1,
freq: 10
}, {
ant: 2,
freq: 10
}, {
ant: 3,
freq: 10
}],
inventoryTime: 400, //设置盘点时长
power: [15, 0, 0, 0] //功率设置
}, function (data) {
console.log(data);
});
\ No newline at end of file
... ...