'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///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;