index.js 8.64 KB
/**
 * @fileOverview 调用入口
 * @author qiqi.zhou@yoho.cn
 */

/**
 * 连接器
 * @type {Connector}
 */
import Connector from './lib/connector';
/**
 * order config
 * @type {Object}
 */
import orders from './lib/interface';
/**
 * uhf dirctive module
 * @type {Uhf}
 */
import Uhf from './lib/directive/uhf';
/**
 * config dirctive module
 * @type {[Config]}
 */
import Config from './lib/directive/config';
/**
 * inventory dirctive module
 * @type {Inventory}
 */
import Inventory from './lib/directive/inventory';

import _ from 'lodash';

import {
    locateOrder
}
from './lib/util';

import appConfig from './config';

/**
 * 读写器初始化模块实例
 * @type {Uhf}
 */
let uhf = new Uhf();
/**
 * 配置读写器实例
 * @type {Config}
 */
let config = new Config();
/**
 * 读写器盘点实例
 * @type {Inventory}
 */
let inventory = new Inventory();

/**
 * 打开读写器
 * @method open
 * @exports index/open
 * @param {String} host 读写器IP
 * @param {Number} port 端口
 * @param {Function} callback 打开成功回调
 */
export let open = function(host, port, callback) {
    if (!host || !port || !callback) {
        throw new Error("错误:ip,端口,回调必须要传");
    }
    //连接一个读写器
    var connector = new Connector({
        host: host,
        port: port
    }, function() {
        uhf.send(connector, orders.openUhf);
    }, receive);
    //当打开读写器模块
    connector.on('openUhf', function(data) {
        if (data.code === 1 || data.code === 2) {
            callback(null, connector);
        } else if (data) {
            var error = new Error(data.message);
            error.code = data.code;
            callback(error);
        }
    });
};

/**
 * 设置功率
 * @method setPower
 * @exports index/setPower
 * @param {Connector} connector 连接器
 * @param {Array}  传参,依次是4个天线的功率 eg: [15,15,15,0]
 */
export let setPower = function(connector, param) {
    config.send(connector, orders.setPower, param);
};

/**
 * 设置灵敏度筛选
 * @method setFilter
 * @exports index/setFilter
 * @param {Connector} connect 连接器
 * param {Object} 是否开启灵敏度和灵敏度值 eg:{on:'1',rssi:-60}
 */
export let setFilter = function(connector, param) {
    config.send(connector, orders.setFilter, param);
};

/**
 * 设置天线驻留时长
 * @method setAntStayTime
 * @exports index/setAntStayTime
 * @param {Connector} connect 连接器
 * @param {Number} param 时长,单位毫秒 eg: 100
 */
export let setAntStayTime = function(connector, param) {
    config.send(connector, orders.setAntStayTime, param);
};

/**
 * 设置固定频率
 * @method setFrequency
 * @exports index/setFrequency
 * @param {Connector} connector 连接器
 * @param {Object} param 天线端口和定频的值 eg: 10
 */
export let setFrequency = function(connector, param) {
    config.send(connector, orders.setFrequency, param);
};

/**
 * 设置盘点时长
 * @method setInventoryTime
 * @exports index/setInventoryTime
 * @param {Connector} connect 连接器
 * @param {Number} param 时长,单位毫秒 eg: 400
 */
export let setInventoryTime = function(connector, param) {
    inventory.send(connector, orders.setInventoryTime, param);
};

/**
 * 开始盘点
 * @method startInventory
 * @exports index/startInventory
 * @param {Connector} connect 连接器
 */
export let startInventory = function(connector) {
    inventory.send(connector, orders.startInventory);
};

/**
 * 结束盘点
 * @method stopInventory
 * @exports index/stopInventory
 * @param {Connector} connector 连接器
 */
export let stopInventory = function(connector) {
    inventory.send(connector, orders.stopInventory);
};

/**
 * 开始间歇盘点封装
 * @method start
 * @exports index/start
 * @param {Object} options 传入的配置参数
 * @param {Function} callback 获取数据的回调
 * @example:
  exports.start({
        host: '172.16.13.6',//IP
        port: '9761',//端口
        filter: {//设置灵敏度的过滤
            'on': '1',
            rssi: -60
        },
        frequencys: 10, //天线的定频
        inventoryTime: 400,//设置盘点时长
        antStayTime: 100,//设置天线驻留时长
        power: [15, 0, 0, 0]//功率设置
    }, function (error,data) {
        //console.log(data);
    });
 */
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) {
            let error = new Error('Error:灵敏度,定频,盘点时长,功率必须要传!');
            callback(error);
        }
        //开启灵敏度过滤
        setFilter(connector, options.filter);
        //设置天线驻留时长
        setAntStayTime(connector, options.antStayTime);
        //开启固定频率
        setFrequency(connector, options.frequency);

        //设置盘点时长
        setInventoryTime(connector, options.inventoryTime);

        //设置功率
        connector.on('setInventoryTime', function(data) {
            setPower(connector, options.power);
        });

        //开始盘点
        connector.on('setPower', function(data) {
            startInventory(connector);
        });

        connector.on('startInventory', function(data) {
            if (data.code !== 2 && !isStop) {

                if (lastRets.length === 0) {
                    lastRets = rets;
                } else {
                    var compResults = compTags(lastRets, rets, goneRets);
                    lastRets = compResults.last;
                    goneRets = compResults.gone;
                }

                callback(connector.connected, rets, goneRets);

                rets = [];
                goneRets = [];
                startInventory(connector);
            } else if (data.code === 2) {
                rets = procTagInfo(rets, data.data, options.group, options.host);
            }
        });
    });
};

/**
 * 停止间歇盘点
 * @method stop
 * @exports index/stop
 */
export let stop = function() {
    isStop = true;
};

/**
 * 当前盘点到的标签与上次标签对比函数
 * @param {Array} lastRets 上次盘点结果集
 * @param {Array} rets 盘点结果集
 * @param {Array} goneRets 离架标签结果集
 * @return {Object} result 包含上次盘点结果集和离架标签结果集的对象
 */
function compTags(lastRets, rets, goneRets) {
    var result = {
        last: [],
        gone: []
    };

    for (var i = 0; i < lastRets.length; i++) {
        var item = lastRets[i];
        var checkedItem = _.findWhere(rets, {
            epc: item.epc
        });
        if (checkedItem === undefined) { // 上次盘点数据不包含在此次数据中
            if (item.speed > 1)
                goneRets.push(item);
        } else {
            lastRets[i] = checkedItem;
        }
    }

    for (var j = 0; j < rets.length; j++) {
        var ele = rets[j];
        if (!_.findWhere(lastRets, {
                epc: ele.epc
            })) {
            lastRets.push(ele);
        }
    }

    result.last = lastRets;
    result.gone = goneRets;

    return result;
}

/**
 * 标签处理
 * @method procTagInfo
 * @param {Array} rets 盘点结果集
 * @param {Object} data 读取一次的内容
 * @param {Number} group 标签所属的群组
 * @param {String} host 读写器IP
 */
function procTagInfo(rets, data, group, host) {
    var now = 1 * new Date();

    for (var j = 0; j < data.length; j++) {
        var item = data[j];
        var checkedItem = _.findWhere(rets, {
            epc: item.epc
        });
        if (checkedItem === undefined) {
            rets.push({
                epc: item.epc,
                rssi: item.rssi,
                ant: item.ant,
                group: group,
                host: host,
                speed: 1,
                updateTime: now
            });
        } else {
            checkedItem.speed++;
        }
    }

    return rets;
}


/**
 * 接收数据处理
 * @method receive
 * @param {Socket} client socket客户端
 * @param {Object} data 接收到的数据
 */
function receive(client, data, err) {
    let className = null,
        ret = null;
    if (!data) {
        return null;
    }
    if (err) {
        throw err;
    }
    className = locateOrder(orders, data).val.directive;

    switch (className) {
        case 'uhf':
            ret = uhf.receive(client, data);
            break;
        case 'config':
            ret = config.receive(client, data);
            break;
        case 'inventory':
            ret = inventory.receive(client, data);
            break;
    }
    return ret;
}