'use strict';
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
// const Device = require('./device');
|
var Thing = require('./thing');
|
var SubDevice = require('./subdevice');
|
|
var _require = require('./utils'),
|
createDebug = _require.createDebug,
|
signUtil = _require.signUtil,
|
tripleExpectNotNull = _require.tripleExpectNotNull,
|
tripleIgnoreCase = _require.tripleIgnoreCase,
|
mqttMatch = _require.mqttMatch,
|
mqttNotMatch = _require.mqttNotMatch,
|
isJsonString = _require.isJsonString;
|
|
var debug = createDebug('gateway');
|
|
var Gateway = function (_Thing) {
|
_inherits(Gateway, _Thing);
|
|
function Gateway(config) {
|
_classCallCheck(this, Gateway);
|
|
// create mqttclient
|
var _this = _possibleConstructorReturn(this, (Gateway.__proto__ || Object.getPrototypeOf(Gateway)).call(this, config));
|
|
_this._createClient(_this.model);
|
// subcribe client event and preset topic
|
_this._subscribeClientEvent();
|
// 子设备管理
|
_this.subDevices = [];
|
// 调试模式标识
|
debug('debugger mode');
|
return _this;
|
}
|
// 入参,设备三元组组成的数组
|
|
|
_createClass(Gateway, [{
|
key: 'addTopo',
|
value: function addTopo(devices, cb) {
|
var signed = devices.map(function (device) {
|
return signUtil(device);
|
});
|
this._publishAlinkMessage({
|
method: this.model.ADD_TOPO_METHOD,
|
pubTopic: this.model.ADD_TOPO_TOPIC,
|
params: signed
|
}, cb);
|
}
|
}, {
|
key: 'getTopo',
|
value: function getTopo(cb) {
|
this._publishAlinkMessage({
|
method: this.model.GET_TOPO_METHOD,
|
pubTopic: this.model.GET_TOPO_TOPIC,
|
params: {}
|
}, cb);
|
}
|
/*
|
{"id" : "123",
|
"version":"1.0",
|
"params" : [{
|
"deviceName" : "deviceName1234",
|
"productKey" : "1234556554"
|
}],
|
"method":"thing.topo.delete" }
|
*/
|
|
}, {
|
key: 'removeTopo',
|
value: function removeTopo(devices, cb) {
|
this._publishAlinkMessage({
|
method: this.model.DELETE_TOPO_METHOD,
|
pubTopic: this.model.DELETE_TOPO_TOPIC,
|
params: devices
|
}, cb);
|
}
|
}, {
|
key: 'login',
|
value: function login(device, cb) {
|
var _this2 = this;
|
|
// 忽略三元组大小写
|
tripleIgnoreCase(device);
|
// 校验三元组非空
|
tripleExpectNotNull(device);
|
// 创建subdevice
|
var subDevice = new SubDevice(device, this);
|
|
this._addSubDevices(subDevice);
|
// 通过网关登录
|
this._publishAlinkMessage({
|
params: signUtil(device),
|
pubTopic: this.model.LOGIN_TOPIC
|
}, function (resp) {
|
cb(resp);
|
if (resp.code === 200) {
|
// gateway subscribe subDevice Topic
|
// subdevice subscribe topic must until subdevice login succeed!
|
_this2._subscribePresetTopic(subDevice);
|
subDevice.emit("connect");
|
} else {
|
subDevice.emit("error", resp);
|
}
|
});
|
|
return subDevice;
|
}
|
}, {
|
key: 'logout',
|
value: function logout(params, cb) {
|
this._publishAlinkMessage({
|
params: params,
|
pubTopic: this.model.LOGOUT_TOPIC
|
}, cb);
|
}
|
|
/*
|
* 网关动态注册子设备
|
"params": [
|
{
|
"deviceName": "deviceName1234",
|
"productKey": "1234556554"
|
}
|
]
|
*/
|
|
}, {
|
key: 'regiestSubDevice',
|
value: function regiestSubDevice(data, cb) {
|
var params = void 0;
|
if (data instanceof Array) {
|
params = data;
|
} else if (data instanceof Object) {
|
params = [data];
|
}
|
this._publishAlinkMessage({
|
method: this.model.SUBDEVICE_REGISTER_METHOD,
|
params: params,
|
pubTopic: this.model.SUBDEVICE_REGISTER_TOPIC
|
}, cb);
|
}
|
|
/*
|
* 重写device message方法,因为消息只发送到网关,所以要通过网关转发到子设备
|
*/
|
|
}, {
|
key: '_mqttCallbackHandler',
|
value: function _mqttCallbackHandler(topic, message) {
|
|
// 情况1:返回值为非结构化数据(非结构化可能是:基础版产品或是用户自定义topic)
|
if (isJsonString(message.toString()) == false) {
|
return;
|
}
|
|
// 开始处理返回值
|
try {
|
var res = JSON.parse(message.toString());
|
var subDevice = void 0;
|
// console.log('gateway _mqttCallbackHandler',topic,res);
|
|
//处理On Props Set回调
|
// topic /sys/<pk>/<dn>/thing/service/property/set
|
subDevice = this._searchMqttMatchOnSetPropsTopicWithSubDevice(topic);
|
if (subDevice) {
|
subDevice._onPropsCB(res);
|
return;
|
}
|
|
//处理子设备服务返回数据,同步或者异步方式
|
subDevice = this._searchMqttMatchServiceTopicWithSubDevice(topic);
|
if (subDevice) {
|
// console.log("gateway _searchMqttMatchServiceTopicWithSubDevice",topic);
|
subDevice._onReceiveService(topic, res);
|
return;
|
}
|
// 处理子设备影子服务回调
|
subDevice = this._searchMqttMatchShadowTopicWithSubDevice(topic);
|
if (subDevice) {
|
// console.log("_searchMqttMatchShadowTopicWithSubDevice");
|
subDevice._onShadowCB(res);
|
return;
|
}
|
|
// 远程配置回调
|
subDevice = this._searchMqttMatchConfigTopicWithSubDevice(topic);
|
if (subDevice) {
|
// console.log("_searchMqttMatchConfigTopicWithSubDevice");
|
subDevice._onConfigCB(res);
|
return;
|
}
|
|
//其他通用回调
|
var cbID = res.id;
|
|
var callback = this._getAllSubDevicesCallback(cbID, topic);
|
// console.log("gateway通用回调",topic,callback,message);
|
if (callback) {
|
callback(res);
|
}
|
} catch (e) {
|
console.log('_mqttCallbackHandler error', e);
|
}
|
|
// device 、gateway message handler
|
_get(Gateway.prototype.__proto__ || Object.getPrototypeOf(Gateway.prototype), '_mqttCallbackHandler', this).call(this, topic, message);
|
}
|
|
// 子设备On Set Porps topic
|
|
}, {
|
key: '_searchMqttMatchOnSetPropsTopicWithSubDevice',
|
value: function _searchMqttMatchOnSetPropsTopicWithSubDevice(topic) {
|
return this._getSubDevices().find(function (subDevice) {
|
return mqttMatch(subDevice.model.ONSET_PROPS_TOPIC, topic);
|
});
|
}
|
// 子设备的服务topic
|
|
}, {
|
key: '_searchMqttMatchServiceTopicWithSubDevice',
|
value: function _searchMqttMatchServiceTopicWithSubDevice(topic) {
|
return this._getSubDevices().find(function (subDevice) {
|
return mqttMatch(subDevice.model.getWildcardServiceTopic(), topic) || mqttMatch(subDevice.model.RRPC_REQ_TOPIC, topic);
|
});
|
}
|
// 子设备影子设备topic
|
|
}, {
|
key: '_searchMqttMatchShadowTopicWithSubDevice',
|
value: function _searchMqttMatchShadowTopicWithSubDevice(topic) {
|
return this._getSubDevices().find(function (subDevice) {
|
return mqttMatch(subDevice.model.SHADOW_SUBSCRIBE_TOPIC, topic);
|
});
|
}
|
// 子设备的远程配置topic
|
|
}, {
|
key: '_searchMqttMatchConfigTopicWithSubDevice',
|
value: function _searchMqttMatchConfigTopicWithSubDevice(topic) {
|
return this._getSubDevices().find(function (subDevice) {
|
return mqttMatch(subDevice.model.getWildcardConfigTopic(), topic) && mqttNotMatch(subDevice.model.CONFIG_REPLY_TOPIC, topic) === true;
|
});
|
}
|
}, {
|
key: '_getSubDevices',
|
value: function _getSubDevices() {
|
if (!this.subDevices) {
|
this.subDevices = [];
|
}
|
return this.subDevices;
|
}
|
}, {
|
key: '_addSubDevices',
|
value: function _addSubDevices(subDevice) {
|
this._getSubDevices().push(subDevice);
|
}
|
}, {
|
key: '_getAllSubDevicesCallback',
|
value: function _getAllSubDevicesCallback(cbID, topic) {
|
var callback = void 0;
|
this._getSubDevices().forEach(function (subDevice) {
|
// console.log('>>>subDevice',subDevice);
|
var cb = subDevice._findCallback(cbID, topic);
|
if (cb) {
|
callback = cb;
|
}
|
return;
|
});
|
return callback;
|
}
|
}]);
|
|
return Gateway;
|
}(Thing);
|
|
module.exports = Gateway;
|