Beispiel #1
0
ObjectInstance.prototype.write = function (rid, value, opt, callback) {
    var self = this,
        rsc = this.get(rid);

    if (_.isFunction(opt)) {
        callback = opt;
        opt = undefined;
    }

    opt = opt || { restrict: false };

    if (!validateResource(rsc, callback))
        return;
    else if (!_.isPlainObject(opt))
        throw new TypeError('opt should be an object if given.');

    function restrictWrite(valToWrite, cb) {
        var rdef = lwm2mId.getRdef(self.oid, rid),
            isWritable = rdef && (rdef.access === 'W' || rdef.access === 'RW');

        if (!rdef || isWritable) {  // no definition is always writable
            self.set(rid, valToWrite);
            return utils.invokeCbNextTick(null, valToWrite, cb);
        } else {
            return utils.invokeCbNextTick(new Error('Resource is unwritable.'), '_unwritable_', cb);
        }
    }

    if (!_.isPlainObject(rsc)) {
        if (!opt.restrict)
            this.set(rid, value);
        return opt.restrict ? restrictWrite(value, callback) : utils.invokeCbNextTick(null, value, callback);
    }

    // if we are here, rsc is a plain object
    if (!rsc._isCb) {
        if (!opt.restrict)
            this.set(rid, value);
        return opt.restrict ? restrictWrite(value, callback) : utils.invokeCbNextTick(null, _.omit(value, [ '_isCb' ]), callback);
    }

    // rsc should be written by users callback
    if (_.isFunction(rsc.exec)) // an exec resource cannot be written, so checks for it first
        return utils.invokeCbNextTick(new Error('Resource is unwritable.'), '_exec_', callback);

    if (!_.isFunction(rsc.write))
        return utils.invokeCbNextTick(new Error('Resource is unwritable.'), '_unwritable_', callback);

    rsc.write(value, function (err, val) {
        utils.invokeCbNextTick(err, val, callback);
    });
};
Beispiel #2
0
Controller.prototype.remove = function (dev, cfg, callback) {
    // cfg: { reJoin, rmChildren }
    var self = this,
        reqArgObj,
        rmChildren_reJoin = 0x00;

    if (!(dev instanceof Device))
        throw new TypeError('dev should be an instance of Device class.');
    else if (!_.isPlainObject(cfg))
        throw new TypeError('cfg should be an object.');

    cfg.reJoin = cfg.hasOwnProperty('reJoin') ? !!cfg.reJoin : true;               // defaults to true
    cfg.rmChildren = cfg.hasOwnProperty('rmChildren') ? !!cfg.rmChildren : false;  // defaults to false

    rmChildren_reJoin = cfg.reJoin ? (rmChildren_reJoin | 0x01) : rmChildren_reJoin;
    rmChildren_reJoin = cfg.rmChildren ? (rmChildren_reJoin | 0x02) : rmChildren_reJoin;

    reqArgObj = {
        dstaddr: dev.getNwkAddr(),
        deviceaddress: dev.getIeeeAddr(),
        removechildren_rejoin: rmChildren_reJoin
    };

    return this.request('ZDO', 'mgmtLeaveReq', reqArgObj).then(function (rsp) {
        if (rsp.status !== 0 && rsp.status !== 'SUCCESS')
            return Q.reject(rsp.status);
    }).nodeify(callback);
};
Beispiel #3
0
ObjectInstance.prototype.init = function (resrcs, setup) {
    // each time of init(), all resources and inner resrcs._state will be cleared. Use .set() to add/modify resource
    var self = this.clear(),
        ridKey;

    if (!_.isPlainObject(resrcs))
        throw new TypeError('Resources should be wrapped in an object.');

    if (!_.isUndefined(setup) && !_.isFunction(setup))
        throw new TypeError('setup should be a function if given.');

    if (!_.isUndefined(resrcs._state)) {
        if (_.isPlainObject(resrcs._state))
            _.assign(this._state, resrcs._state);
        else
            throw new TypeError('resrcs._state must be an object if given.');

        delete resrcs._state;
    }

    _.forEach(resrcs, function (rVal, rKey) {
        if (self.parent.ipsoOnly) {
            if (!lwm2mId.getRid(self.oid, rKey))
                throw new TypeError('Resource id: ' + rKey + ' is not an IPSO-defined resource.');
        }

        if (_.isObject(rVal)) {
            rVal._isCb = _.isFunction(rVal.read) || _.isFunction(rVal.write) || _.isFunction(rVal.exec);

            if (_.isFunction(rVal.read))
                rVal.read = rVal.read.bind(self);

            if (_.isFunction(rVal.write))
                rVal.write = rVal.write.bind(self);

            if (_.isFunction(rVal.exec))
                rVal.exec = rVal.exec.bind(self);
        }

        self.set(rKey, rVal);   // set will turn rid to string
    });

    if (_.isFunction(setup))
        setup.call(this);
};
Beispiel #4
0
ObjectInstance.prototype.read = function (rid, opt, callback) {
    var self = this,
        rsc = this.get(rid);

    if (_.isFunction(opt)) {
        callback = opt;
        opt = undefined;
    }

    opt = opt || { restrict: false };

    if (!validateResource(rsc, callback))
        return;
    else if (!_.isPlainObject(opt))
        throw new TypeError('opt should be an object if given.');

    function restrictRead(rsc, cb) {
        var rdef = lwm2mId.getRdef(self.oid, rid),
            isReadable = rdef && (rdef.access === 'R' || rdef.access === 'RW');

        if (!rdef || isReadable)    // no definition is always readable
            return utils.invokeCbNextTick(null, rsc, cb);
        else
            utils.invokeCbNextTick(new Error('Resource is unreadable.'), '_unreadable_', cb);
    }

    if (!_.isPlainObject(rsc))
        return opt.restrict ? restrictRead(rsc, callback) : utils.invokeCbNextTick(null, rsc, callback);

    // if we are here, rsc is a plain object
    if (!rsc._isCb)
        return opt.restrict ? restrictRead(rsc, callback) : utils.invokeCbNextTick(null, _.omit(rsc, [ '_isCb' ]), callback);

    // rsc should be read from users callback
    if (_.isFunction(rsc.exec)) // an exec resource cannot be read, so checks for it first
        return utils.invokeCbNextTick(new Error('Resource is unreadable.'), '_exec_', callback);

    if (!_.isFunction(rsc.read))
        return utils.invokeCbNextTick(new Error('Resource is unreadable.'), '_unreadable_', callback);

    rsc.read(function (err, val) {
        utils.invokeCbNextTick(err, val, callback);
    });
};
Beispiel #5
0
Controller.prototype.request = function (subsys, cmdId, valObj, callback) {
    var deferred = Q.defer(),
        rspHdlr;

    proving.stringOrNumber(subsys, 'subsys should be a number or a string.');
    proving.stringOrNumber(cmdId, 'cmdId should be a number or a string.');

    if (!_.isPlainObject(valObj) && !_.isArray(valObj))
        throw new TypeError('valObj should be an object or an array.');

    if (_.isString(subsys))
        subsys = subsys.toUpperCase();

    rspHdlr = function (err, rsp) {
        if (subsys !== 'ZDO' && subsys !== 5) {
            if (rsp && rsp.hasOwnProperty('status'))
                debug.request('RSP <-- %s, status: %d', subsys + ':' + cmdId, rsp.status);
            else
                debug.request('RSP <-- %s', subsys + ':' + cmdId);
        }

        if (err)
            deferred.reject(err);
        else if ((subsys !== 'ZDO' && subsys !== 5) && rsp && rsp.hasOwnProperty('status') && rsp.status !== 0)  // unsuccessful
            deferred.reject(new Error('rsp error: ' + rsp.status));
        else
            deferred.resolve(rsp);
    };

    if ((subsys === 'AF' || subsys === 4) && valObj.hasOwnProperty('transid'))
        debug.request('REQ --> %s, transId: %d', subsys + ':' + cmdId, valObj.transid);
    else
        debug.request('REQ --> %s', subsys + ':' + cmdId);

    if (subsys === 'ZDO' || subsys === 5)
        this._zdo.request(cmdId, valObj, rspHdlr);          // use wrapped zdo as the exported api
    else
        this._znp.request(subsys, cmdId, valObj, rspHdlr);  // SREQ has timeout inside znp

    return deferred.promise.nodeify(callback);
};
module.exports = function (name, settings) {
    if (!_.isString(name)) {
        settings = name;
        name = undefined;
    }

    if (!_.isUndefined(settings) && !_.isPlainObject(settings))
        throw new TypeError('settings should be an object if given.');

    var netcore,
        ncName = (name || 'freebird-netcore-mqtt'),
        shepherd = new MqttShepherd(ncName, settings),
        drivers = require('./drivers/drivers.js')(shepherd);

    /***********************************************************************/
    /*** Create Netcore                                                  ***/
    /***********************************************************************/
    netcore = fBase.createNetcore(ncName, shepherd, {
        phy: 'ieee802',
        tl: 'tcp',
        nwk: 'ip',
        apl: 'mqtt'
    });

    netcore._cookRawDev = cookRawDev;
    netcore._cookRawGad = cookRawGad;

    netcore.registerNetDrivers(drivers.net);
    netcore.registerDevDrivers(drivers.dev);
    netcore.registerGadDrivers(drivers.gad);

    /***********************************************************************/
    /*** Event Transducer                                                ***/
    /***********************************************************************/
    shepherd.on('error', function (err) {
        if (_.isFunction(netcore.commitError))
            netcore.commitError('net', err);
    });

    shepherd.on('ready', function () {
        netcore.commitReady();  // netcore.enable() inside netcore
    });

    shepherd.on('ind', function (msg) {
        var type = msg.type,
            qnode = msg.qnode;  // just pass qnode, no need to dump first

        switch (type) {
            case 'devIncoming':
                msgHdlrs.devIncoming(netcore, qnode);
                break;
            case 'devLeaving':
                var macAddr = msg.data,
                    cliendId = qnode,
                    permAddr = helper.buildPermAddr(macAddr, cliendId);
                msgHdlrs.devLeaving(netcore, permAddr);
                break;
            case 'devUpdate':
                var devAttrChanges = msg.data;
                msgHdlrs.devUpdate(netcore, qnode, devAttrChanges);
                break;
            case 'devNotify':
                var devAttrNotified = msg.data;
                msgHdlrs.devNotify(netcore, qnode, devAttrNotified);
                break;
            case 'devChange':
                msgHdlrs.devChange(netcore, qnode, msg.data);
                break;
            case 'devStatus':
                var statusString = msg.data;
                msgHdlrs.devStatus(netcore, qnode, statusString);
                break;
            default:
                break;
        }
    });

    return netcore;
};
Beispiel #7
0
function Controller(shepherd, cfg) {
    // cfg is serial port config
    var self = this,
        transId = 0;

    EventEmitter.call(this);

    if (!_.isPlainObject(cfg))
        throw new TypeError('cfg should be an object.');

    /***************************************************/
    /*** Protected Members                           ***/
    /***************************************************/
    this._shepherd = shepherd;
    this._coord = null;
    this._znp = znp;
    this._cfg = cfg;
    this._zdo = new Zdo(this);
    this._resetting = false;
    this._spinLock = false;
    this._joinQueue = [];
    this._permitJoinTime = 0;
    this._permitJoinInterval;

    this._net = {
        state: null,
        channel: null,
        panId: null,
        extPanId: null,
        ieeeAddr: null,
        nwkAddr: null,
        joinTimeLeft: 0
    };

    /***************************************************/
    /*** Public Members                              ***/
    /***************************************************/
    this.querie = querie(this);

    this.nextTransId = function () {  // zigbee transection id
        if (++transId > 255)
            transId = 1;
        return transId;
    };

    this.permitJoinCountdown = function () {
        return self._permitJoinTime -= 1;
    };

    this.isResetting = function () {
        return self._resetting;
    };

    /***************************************************/
    /*** Event Handlers                              ***/
    /***************************************************/
    this._znp.on('ready', function () {
        init.setupCoord(self).then(function () {
            self.emit('ZNP:INIT');
        }).fail(function (err) {
            self.emit('ZNP:INIT', err);
            debug.init('Coordinator initialize had an error:', err);
        }).done();
    });

    this._znp.on('close', function () {
        self.emit('ZNP:CLOSE');
    });

    this._znp.on('AREQ', function (msg) {
        bridge._areqEventBridge(self, msg);
    });

    this.on('ZDO:endDeviceAnnceInd', function (data) {
        console.log('spinlock:', self._spinLock, self._joinQueue);
        if (self._spinLock) {
            // Check if joinQueue already has this device
            for (var i = 0; i < self._joinQueue.length; i++) {
                if (self._joinQueue[i].ieeeAddr == data.ieeeaddr) {
                    console.log('already in joinqueue');
                    return;
                }
            }

            self._joinQueue.push({
                func: function () {
                    self.endDeviceAnnceHdlr(data);
                },
                ieeeAddr: data.ieeeaddr
            });
        } else {
            self._spinLock = true;
            self.endDeviceAnnceHdlr(data);
        }
    });
}