Authored by Rock Zhang

修复读写器设置的bug,原因是异步发送多条设置指令时,返回的结果指令会拼接到一起,而拆分函数处理时存在bug

... ... @@ -11,6 +11,10 @@ title: 读写器的SDK
* 打开读写器(A0 00 00 00 00)
* 关闭读写器(A1 00 00 00 00)
* 设置功率(F3 10 00 00 00)
* 设置频率区域(F5 00 00 00 00)
* 设置速度模式(FA 00 00 00 00)
* 设置标签组(B6 00 00 00 00)
* 设置天线驻留时长(CA 00 00 00 00)
* 设置定频(BF 00 00 00 00)
* 获取配置(B3 00 00 00 00)
* 开始盘点(F1 00 00 00 00)
... ... @@ -107,4 +111,5 @@ sdk.start({
1. 对于多个返回结果的拆分(已解决)
2. 设置定频,没有起作用(待验证)
3. socket连接异常处理
\ No newline at end of file
3. socket连接异常处理
4. 读写器有时会返回不到盘点的标签数据
\ No newline at end of file
... ...
... ... @@ -8,7 +8,7 @@
* inventory_time: 盘点时间
*/
var readers = [
{
/*{
id: 1,
readerId: 1,
readerIp: '172.16.13.5',
... ... @@ -16,7 +16,7 @@ var readers = [
frequency: 912.75,
stay_time: 200,
inventory_time: 500
},
},*/
{
id: 2,
readerId: 2,
... ... @@ -48,7 +48,7 @@ var readers = [
id: 5,
readerId: 5,
readerIp: '172.16.13.86',
rssi: -75,
rssi: -65,
frequency: 924.75,
stay_time: 100,
inventory_time: 500
... ... @@ -106,7 +106,7 @@ var readers = [
frequency: 923.75,
stay_time: 100,
inventory_time: 500
}/*,
},
{
id: 12,
readerId: 12,
... ... @@ -115,7 +115,7 @@ var readers = [
frequency: 923.75,
stay_time: 100,
inventory_time: 500
}*/
}
];
/**
* 读写器天线数据
... ...
... ... @@ -2,7 +2,7 @@ var net = require('net'),
redis = require('redis'),
_ = require('lodash'),
async = require('async'),
index = require('../src/index.js'),
index = require('../index.js'),
readerConfig = require('./readerConfig.js');
var r = redis.createClient();
... ... @@ -127,7 +127,7 @@ function connectAllReaders()
var reader = readers[ip];
var filter = {
'on': '1',
rssi: reader.rssi*10
rssi: reader.rssi
};
var frequency = 10;
... ... @@ -167,7 +167,7 @@ function connectReader(host, port, filter, frequency, inventoryTime, antStayTime
antStayTime: antStayTime,
power: power,
group: group
}, function (connected, onTags, goneTags) {
}, function (err, connected, onTags, goneTags) {
var onEpcs = [],
offEpcs = [];
... ... @@ -184,37 +184,38 @@ function connectReader(host, port, filter, frequency, inventoryTime, antStayTime
try
{
var redisEpcs = JSON.parse(epcs);
// 处理在架标签
_.forEach(redisEpcs, function(item){
if(item.speed > 2 && item.host != host && _.findWhere(onTags, {epc: item.epc}) === undefined){
onEpcs.push({
GroupID: item.group,
EPC: item.epc,
updateTime: item.updateTime
});
if(item.host != host && _.findWhere(onTags, {epc: item.epc}) === undefined){
onEpcs.push(item);
}
});
_.forEach(onTags, function(item){
onEpcs.push({
GroupID: item.group,
EPC: item.epc,
host: item.host,
speed: item.speed,
updateTime: item.updateTime
});
});
r.hset(group, 'on', JSON.stringify(onEpcs), function(){});
// 处理离架标签
_.forEach(goneTags, function(goneEpc){
if(!goneEpc || _.findWhere(redisEpcs, {epc: goneEpc.epc}) === undefined){
if(!goneEpc || (_.findWhere(redisEpcs, {EPC: goneEpc.epc}) === undefined && _.findWhere(onTags, {epc: goneEpc.epc}) === undefined)){
offEpcs.push({
GroupID: goneEpc.group,
EPC: goneEpc.epc,
host: goneEpc.host,
speed: goneEpc.speed,
rssi: goneEpc.rssi,
updateTime: goneEpc.updateTime
});
}
});
r.hset(group, 'on', JSON.stringify(onEpcs), function(){});
r.hset(group, 'off', JSON.stringify(offEpcs), function(){});
if(connected){
... ... @@ -233,6 +234,67 @@ function connectReader(host, port, filter, frequency, inventoryTime, antStayTime
});
}
function processOnTags()
{
// 获取redis中指定组在架标签数据
r.hget(group, 'on', function(err, epcs)
{
if (err)
{
console.error(err);
}
else
{
try
{
var redisEpcs = JSON.parse(epcs);
// 处理在架标签
_.forEach(redisEpcs, function(item){
if(item.host != host && _.findWhere(onTags, {epc: item.epc}) === undefined){
onEpcs.push(item);
}
});
_.forEach(onTags, function(item){
onEpcs.push({
GroupID: item.group,
EPC: item.epc,
host: item.host,
speed: item.speed,
updateTime: item.updateTime
});
});
r.hset(group, 'on', JSON.stringify(onEpcs), function(){});
// 处理离架标签
_.forEach(goneTags, function(goneEpc){
if(!goneEpc || _.findWhere(redisEpcs, {EPC: goneEpc.epc}) === undefined){
offEpcs.push({
GroupID: goneEpc.group,
EPC: goneEpc.epc,
host: goneEpc.host,
speed: goneEpc.speed,
rssi: goneEpc.rssi,
updateTime: goneEpc.updateTime
});
}
});
r.hset(group, 'off', JSON.stringify(offEpcs), function(){});
if(connected){
callback(null, connected);
}else{
callback(new Error('连接读写器'+host+'错误'), connected);
}
}
catch(er)
{
console.error('标签数据JSON格式错误:'+er);
}
}
});
}
/**
* 获取指定时间和当前时间的差异
* @param val 指定的时间
... ...
... ... @@ -7,6 +7,7 @@
"dependencies": {
"async": "0.9.0",
"babel": "5.x.x",
"babel-core": "^5.4.3",
"lodash": "3.6.x",
"log4js": "0.6.x",
"pm2": "~0.12.3",
... ... @@ -29,4 +30,4 @@
"rewire": "*",
"babel-plugin-rewire": "*"
}
}
\ No newline at end of file
}
... ...
... ... @@ -9,8 +9,5 @@
*/
export default {
log: './log',
logLevel: 'INFO',
checkInventory: 200,
offInventory: 500,
checkCount: 1000
logLevel: 'INFO'
};
\ No newline at end of file
... ...
... ... @@ -54,6 +54,17 @@ let config = new Config();
*/
let inventory = new Inventory();
import log4js from 'log4js';
let loger = log4js.getLogger('log');
loger.setLevel(config.logLevel); //配置日志
/**
* @mixes 日志记录对象
* @exports util/log
*/
export let log = loger;
/**
* 打开读写器
* @method open
... ... @@ -83,6 +94,7 @@ export let open = function(host, port, callback) {
callback(error);
}
});
};
/**
... ... @@ -130,6 +142,42 @@ export let setFrequency = function(connector, param) {
};
/**
* 设置频率区域
* @method setFrequencyRegion
* @exports index/setFrequencyRegion
* @param {Connector} connector 连接器
* @param {Object} param 频率区域的值 eg: 0:FCC,1:CCC,2:NCC,3:JPN
*/
export let setFrequencyRegion = function(connector, param) {
config.send(connector, orders.setFrequencyRegion, param);
};
/**
* 设置速度模式
* @method setSpeedMode
* @exports index/setSpeedMode
* @param {Connector} connector 连接器
* @param {Object} param 速度模式的值 eg: 0:高速,1:正常速度,2:省电模式
*/
export let setSpeedMode = function(connector, param) {
config.send(connector, orders.setSpeedMode, param);
};
/**
* 设置标签组
* @method setTagGroup
* @exports index/setTagGroup
* @param {Connector} connector 连接器
* @param {Object} param 标签组的值 eg: {'session':0,'target':0,'search_mode':1}
* 其中session:0代表S0,1代表S1,2代表S2,3代表S3
* target:0代表A,1代表B
* search_mode:0代表DUAL_TARGET,1代表SINGLE_TARGET,2代表SINGLE_TARGET_WITH_SUPPRESSION
*/
export let setTagGroup = function(connector, param) {
config.send(connector, orders.setTagGroup, param);
};
/**
* 设置盘点时长
* @method setInventoryTime
* @exports index/setInventoryTime
... ... @@ -147,6 +195,7 @@ export let setInventoryTime = function(connector, param) {
* @param {Connector} connect 连接器
*/
export let startInventory = function(connector) {
inventory.send(connector, orders.startInventory);
};
... ... @@ -183,28 +232,50 @@ export let stopInventory = function(connector) {
});
*/
let isStop = false;
export let start = function(options, callback) {
var lastRets = [],
rets = [],
goneRets = [];
open(options.host, options.port, function(err, connector) {
if (!options.filter || !options.frequencys || !options.inventoryTime || !options.power || !options.antStayTime) {
if (!options.filter || !options.frequency || !options.inventoryTime || !options.power || !options.antStayTime) {
let error = new Error('Error:灵敏度,定频,盘点时长,功率必须要传!');
callback(error);
return;
}
//开启灵敏度过滤
setFilter(connector, options.filter);
//设置天线驻留时长
setAntStayTime(connector, options.antStayTime);
connector.on('setFilter', function(data) {
setAntStayTime(connector, options.antStayTime);
});
//设置频率区域
connector.on('setAntStayTime', function(data) {
setFrequencyRegion(connector, 1); // 设置频率区域为CCC
});
//设置速度模式
connector.on('setFrequencyRegion', function(data) {
setSpeedMode(connector, 0); // 设置速度模式为高速
});
//设置标签组
connector.on('setSpeedMode', function(data) {
setTagGroup(connector, {'session':0,'target':0,'search_mode':1}); // 设置标签组:session:S0,target:A,search_mode:单目标
});
//开启固定频率
setFrequency(connector, options.frequency);
connector.on('setTagGroup', function(data) {
setFrequency(connector, options.frequency);
});
//设置盘点时长
setInventoryTime(connector, options.inventoryTime);
connector.on('setFrequency', function(data) {
setInventoryTime(connector, options.inventoryTime);
});
//设置功率
connector.on('setInventoryTime', function(data) {
setPower(connector, options.power);
});
... ... @@ -216,6 +287,10 @@ export let start = function(options, callback) {
connector.on('startInventory', function(data) {
if (data.code !== 2 && !isStop) {
rets = _.filter(rets, function(item){
return item.speed > 1;
});
if (lastRets.length === 0) {
lastRets = rets;
} else {
... ... @@ -224,15 +299,17 @@ export let start = function(options, callback) {
goneRets = compResults.gone;
}
callback(connector.connected, rets, goneRets);
callback(null, connector.connected, rets, goneRets);
rets = [];
goneRets = [];
startInventory(connector);
} else if (data.code === 2) {
rets = procTagInfo(rets, data.data, options.group, options.host);
}
});
});
};
... ... @@ -263,8 +340,9 @@ function compTags(lastRets, rets, goneRets) {
var checkedItem = _.findWhere(rets, {
epc: item.epc
});
if (checkedItem === undefined) { // 上次盘点数据不包含在此次数据中
if (item.speed > 1)
if (item.speed > 2 || item.rssi > -60)
goneRets.push(item);
} else {
lastRets[i] = checkedItem;
... ... @@ -339,6 +417,7 @@ function receive(client, data, err) {
if (err) {
throw err;
}
className = locateOrder(orders, data).val.directive;
switch (className) {
... ...
... ... @@ -55,11 +55,18 @@ class Connector extends events.EventEmitter {
orderName = locateOrder(orders, rets.rets[i]).name; //指令名称
returnData = receive(client, rets.rets[i]); //接收返回
that.emit(orderName, returnData); //触发接收数据的指令事件
}
});
client.setTimeout(2000, function(){
// 读写器连接错误或者突然断开
this.connected = false;
// 触发重连事件
that.emit('reconnect', config);
});
//异常处理
client.on('error', function(error) {
log.error('错误:' + error.code);
... ... @@ -73,6 +80,7 @@ class Connector extends events.EventEmitter {
client.on('close', function() {
log.info('读写器连接断开');
// 触发重连事件
that.emit('reconnect');
});
... ...
... ... @@ -40,6 +40,7 @@ class Base {
if (this.reproc[order.input]) {
sendOrder = this.reproc[order.input](param);
}
console.log(sendOrder);
connector.send(sendOrder);
let address = connector.client.remoteAddress;
//log.info('读写器(' + address + ')发送指令:' + sendOrder);
... ...
... ... @@ -28,12 +28,18 @@ class Config extends Base {
let power = info.setPower.input,
filter = info.setFilter.input,
stayTime = info.setAntStayTime.input,
frequency = info.setFrequency.input;
frequency = info.setFrequency.input,
frequencyRegion = info.setFrequencyRegion.input,
speedMode = info.setSpeedMode.input,
tagGroup = info.setTagGroup.input;
this.reproc[power] = this.prePower;
this.reproc[filter] = this.preFilter;
this.reproc[stayTime] = this.preStayTime;
this.reproc[frequency] = this.preFrequency;
this.reproc[frequencyRegion] = this.preFrequencyRegion;
this.reproc[speedMode] = this.preSpeedMode;
this.reproc[tagGroup] = this.preTagGroup;
}
/**
... ... @@ -137,6 +143,42 @@ class Config extends Base {
freq = freq.length < 2 ? ('0' + freq) : freq;
return info.setFrequency.input + freq + '000000';
}
/**
* @method preFrequencyRegion
* @description 设置频率区域
* @param {Object} param 频率区域的值 eg: 0:FCC,1:CCC,2:NCC,3:JPN
*/
preFrequencyRegion(param) {
return info.setFrequencyRegion.input + '0' + tenToHex(param).toLocaleUpperCase() + '000000';
}
/**
* @method preSpeedMode
* @description 设置速度模式
* @param {Object} param 速度模式的值 eg: 0:高速,1:正常速度,2:省电模式
*/
preSpeedMode(param) {
return info.setSpeedMode.input + '0' + tenToHex(param).toLocaleUpperCase() + '000000';
}
/**
* @method preTagGroup
* @description 设置标签组预处理
* @param {Object} param 标签组的值 eg: {'session':0,'target':0,'search_mode':1}
* 其中session:0代表S0,1代表S1,2代表S2,3代表S3
* target:0代表A,1代表B
* search_mode:0代表DUAL_TARGET,1代表SINGLE_TARGET,2代表SINGLE_TARGET_WITH_SUPPRESSION
*/
preTagGroup(param) {
let session = '0'+tenToHex(param.session * 10).toLocaleUpperCase(),
target = '0'+tenToHex(param.target).toLocaleUpperCase(),
search_mode = '0'+tenToHex(param.search_mode).toLocaleUpperCase();
return info.setTagGroup.input + session +target + search_mode + '00';
}
}
/**
* @exports lib/directive/Config
... ...
... ... @@ -91,6 +91,36 @@ export default {
'bf2ff0': commonMessage.ff0
}
},
setFrequencyRegion: {
directive: 'config',
input: 'F5',
output: {
'f5200': commonMessage['00'],
'f52ffff': commonMessage.ffff,
'f52fffe': commonMessage.fffe,
'f52ff0': commonMessage.ff0
}
},
setSpeedMode: {
directive: 'config',
input: 'FA',
output: {
'fa200': commonMessage['00'],
'fa2ffff': commonMessage.ffff,
'fa2fffe': commonMessage.fffe,
'fa2ff0': commonMessage.ff0
}
},
setTagGroup: {
directive: 'config',
input: 'B6',
output: {
'b6200': commonMessage['00'],
'b62ffff': commonMessage.ffff,
'b62fffe': commonMessage.fffe,
'b62ff0': commonMessage.ff0
}
},
getConfig: {
directive: 'uhf',
input: 'B300000000',
... ... @@ -125,6 +155,10 @@ export default {
code: 2,
message: '返回信息'
},
'41': {
code: 3,
message: '不明飞行物'
},
'f1239': {
code: 889,
message: '未知错误'
... ...
... ... @@ -76,9 +76,9 @@ export let returnProc = function(data, ip, output) {
let ret = data.join('');
if (!output[ret]) {
return false;
return {};
}
log.info("读写器(" + ip + ")返回:" + output[ret].message + " 返回码:" + ret);
//log.info("读写器(" + ip + ")返回:" + output[ret].message + " 返回码:" + ret);
output[ret].hex = data;
return output[ret];
};
... ...
... ... @@ -136,12 +136,12 @@ describe('index.js', function() {
'on': '1',
rssi: -60
},
frequencys: 10,
frequency: 10,
antStayTime: 100,
inventoryTime: 400, //设置盘点时长
power: [15, 0, 0, 0] //功率设置
},
function(connected, data) {
function(err, connected, data) {
expect(data).to.have.length(1);
done();
})
... ...