UNPKG

onem2m_client

Version:

Synctechno's Library for communicating with Mobius on KETI through oneM2M platform

257 lines (212 loc) 6.93 kB
module.exports = function(CONFIG) { var Mqtt, MqttClients, Uuid, _, util, debug, onem2mModel; Mqtt = require('mqtt'); Uuid = require('uuid'); _ = require('lodash'); util = require('util'); debug = require('debug')('keti'); onem2mModel = require('./onem2m-model.js'); MqttClients = {}; var MqttClient = function(mqttServerAddress, from) { var thisObj = this; thisObj.mqttServerAddress = mqttServerAddress; thisObj.from = from; thisObj.eventHandlers = []; thisObj.mqttClient = Mqtt.connect(mqttServerAddress); thisObj.mqttClient.on('connect', function () { mqttSubscribe(thisObj.mqttClient, from); }); thisObj.mqttClient.on('message', mqttMessageHandler); /** * * @param {*} mqttClient * @param {String} origin */ function mqttSubscribe(mqttClient, origin) { /* SPEC: TS-0010-V2.4.1 MQTT Protocol Binding 6.4.2 Sending a Request /oneM2M/req/<originator>/<receiver>/<type> - <receiver> is the SP-relative-AE-ID or SP-relative-CSE-ID of the Receiver (AE, Transit CSE or Hosting CSE) on this hop, omitting any leading */ var aeTopicName = origin; // if SP-relative-AE-ID or SP-relative-CSE-ID if( aeTopicName.startsWith("/") ) { aeTopicName = aeTopicName.substring(1); } aeTopicName = aeTopicName.replace('/', ':'); // subscribe onem2m requet topic var reqTopic = util.format('/oneM2M/req/+/%s/#', aeTopicName); debug( 'SUBSCRIBE MQTT : ' + reqTopic ); mqttClient.subscribe(reqTopic); } function mqttMessageHandler(topic, message) { debug(topic + " :: " + message ); var topicArray = topic.split('/'); var topicFrom = topicArray[3]; var topicTo = topicArray[4]; var topicParams = topicArray.splice(5); // mqtt req primitive param changed on Mobius 2.0 var mesgObj = null; try { mesgObj = JSON.parse(message.toString()); } catch(ex) { debug(ex); } if(mesgObj == null) return; var primitiveParameters = null; if( !mesgObj['m2m:rqp'] ) // message가 request primitive인 경우만 처리 primitiveParameters = mesgObj; else primitiveParameters = mesgObj['m2m:rqp']; //var primitiveParameters = mesgObj['m2m:rqp']; var operation = primitiveParameters['op']; var to = primitiveParameters['to']; var from = primitiveParameters['fr']; var reqId = primitiveParameters['rqi']; if( operation != '5' ) // notification operation만 처리 return; var notiEventType = primitiveParameters['net']; var primitiveContent = primitiveParameters['pc']; if(typeof(notiEventType) == 'string'){ primitiveContent.notiEventType = parseInt(notiEventType); } var handler = thisObj.eventHandlers['notification']; if( handler ) { var handled = handler(thisObj.mqttServerAddress, topicTo, topicParams, notiEventType, primitiveContent); // var handled = handler(thisObj.mqttServerAddress, primitiveContent); if(handled) { // publish response var respObj = { 'm2m:rsp': { 'rsc': '2000', 'to': '', 'fr': thisObj.from, 'rqi': reqId, 'pc': '' } }; var respTopic = "/oneM2M/resp/" + topicFrom + "/" + topicTo + "/json"; thisObj.mqttClient.publish(respTopic, JSON.stringify(respObj)); } } } }; /** * @typedef {Object} mqttHandleData * @property {String} representation * - nev/rep * @property {Number|String} notiEventType * - 1 : resource's infomation was modified * - 2 : resource was removed * - 3 : resource's child was created * - 4 : resource's cihld was removed * @property {Number|String} resourceType * @property {String} resourcePath * @property {Number|String} resourceTypeCode * - 1 AccessControlPolicy(ACP) * - 2 AE * - 3 Container(CNT) * - 4 ContentInstance(CIN) * - 5 CSEBase * - 6 Delivery * - 7 EventConfig * - 8 ExecInstance * - 9 FanOutPoint * - 10 Group * - 11 LocalPolicy * - 12 M2mServiceSubscription * - 13 MgmtCmd * - 14 MgmtObj * - 15 Node * - 16 NodeInfo * - 17 PollingChannel * - 18 RemoteCSE * - 19 Request * - 20 Schedule * - 21 StatsCollect * - 22 StatsConfig * - 23 Subscription * @property {Object} resource */ /** * This callback is displayed as a global member. * @callback mqttCallback * @param {String} mqttAddress * @param {String} topicTo * @param {String} topicParams * @param {Number} notiEventType * @param {mqttHandleData} primitiveContent * */ /** * @param {string} event EnventName * @param {mqttCallback} mqttCallback */ MqttClient.prototype.on = function(event, mqttCallback) { this.eventHandlers[event] = function(mqttServerAddress, topicTo, topicParams, notiEventType, primitiveContent){ try{ var sgn = primitiveContent['sgn'] || primitiveContent['m2m:sgn']; if(sgn.vrq) { return; } var data = {}; data.representation = sgn.nev.rep; data.notiEventType = sgn.net||sgn.nev.net; data.resourceType = _.keys(data.representation)[0]; data.resourcePath = sgn.sur; data.resource = sgn.nev.rep[data.resourceType]; data.resourceTypeCode = onem2mModel.Resource.getTypeCode(data.resourceType); return mqttCallback(mqttServerAddress, topicTo, topicParams, notiEventType, data); }catch(err){ console.error(err); } }; } MqttClient.prototype.off = function(event, handler) { if(this.eventHandlers[event]) delete this.eventHandlers[event]; } return { getClient: getClient, Disconnect: Disconnect, Subscribe: Subscribe, Unsubscribe: Unsubscribe }; /** * * @param {string} to mqttAddress * @param {string} from * @returns {MqttClient} */ function getClient(to, from) { if( !(from && to) ) return null; var mqttServerAddress = ''; if( to.startsWith('mqtt://') ) mqttServerAddress = to; else mqttServerAddress = 'mqtt://' + to; if( ! MqttClients[mqttServerAddress] ) { MqttClients[mqttServerAddress] = new MqttClient(mqttServerAddress, from); } return MqttClients[mqttServerAddress]; } /** * @method Disconnect this feature isn't ready * @param {string} from */ function Disconnect(from) {} /** * @method Subscribe this feature isn't ready * @param {string} topic */ function Subscribe(topic) {} /** * @method Unsubscribe this feature isn't ready * @param {string} topic */ function Unsubscribe(topic) {} }