onem2m_client
Version:
Synctechno's Library for communicating with Mobius on KETI through oneM2M platform
435 lines (378 loc) • 12.8 kB
JavaScript
module.exports = function(CONFIG) {
var exports, Http, Uuid, _, debug, onem2mModel;
Http = require('request-promise');
Uuid = require('uuid');
_ = require('lodash');
debug = require('debug')('keti');
onem2mModel = require('./onem2m-model.js');
return {
getResource: GetResource,
discoverResource: DiscoverResource,
discoverDirectChildResource: DiscoverDirectChildResource,
discoverChildInstance: DiscoverChildInstance,
createResource: CreateResource,
deleteResource: DeleteResource,
subscribeTo : SubscribeTo,
unSubscribeFrom : UnSubscribeFrom
};
/**
* @method GetResource
* @param {string} resourceUrl URL like (server_address/mp_url/cb/ae?/cnt?)
* @param {string} origin requester default 'SOrigin'
* @returns {Promise}
*/
function GetResource(resourceUrl, origin) {
if(!resourceUrl || resourceUrl.length < 1){
throw new Error("resourceUrl is unusable data! please check your resourceUrl")
}
origin = fnDefaultOrigin(origin);
debug( 'GetResource is called with url: ' + resourceUrl + ', origin: ' + origin);
return new Promise(function(resolved, rejected) {
var options = {
method: 'GET',
uri: resourceUrl,
headers: {
"Accept": "application/json",
"nmtype": "short",
"X-M2M-RI": Uuid.v4(),
"X-M2M-Origin": origin
},
json: true,
time: true,
resolveWithFullResponse: true
};
Http(options)
.then(function(result) {
debug( 'success to get resource information ' + result );
result = result.body;
resolved(result);
})
.catch(function(error) {
debug( 'fail to get resource information ' + error );
rejected(error);
});
});
}
/**
* @method DiscoverResource Get URI of children resource list
* @param {string} resourceUrl URL like (server_address/mp_url/cb/ae?/cnt?)
* @param {string} origin Requester default 'SOrigin'
* @param {number|Array<number>} type Yype of wanted resource
* @param {number} limit Max value getting resources
* @param {number} offset
* @returns {Promise}
*/
function DiscoverResource(resourceUrl, origin, type, limit, offset) {
if(!resourceUrl || resourceUrl.length < 1){
throw new Error("resourceUrl is unusable data! please check your resourceUrl")
}
origin = fnDefaultOrigin(origin);
debug( 'DiscoverResource is called with url: ' + resourceUrl + ', origin: ' + origin + ', type: ' + type + ', limit: ' + limit);
return new Promise(function(resolved, rejected) {
var filterCriteria = '?fu=1';
if( type ) {
if(type instanceof Array){
type.forEach((ty)=> {
filterCriteria += '&ty=' + ty;
})
}else{
filterCriteria += '&ty=' + type;
}
}
if( limit ) {
filterCriteria += '&lim=' + limit;
}
else if (type == '4' || type == '26') { // contentInstance or timeseriseInstance 인 경우 limit를 5로 제한
filterCriteria += '&lim=' + CONFIG.limit;
}
if( offset ) {
filterCriteria += '&ofst=' + offset;
}
filterCriteria += '&lvl=1';
var options = {
method: 'GET',
uri: resourceUrl + filterCriteria,
headers: {
"Accept": "application/json",
"nmtype": "short",
"X-M2M-RI": Uuid.v4(),
"X-M2M-Origin": origin
},
json: true
};
debug( "DISCOVER : " + resourceUrl + filterCriteria);
Http(options)
.then(function(result) {
debug( 'success to discover resource('+type+') information ' + result['m2m:uril'] );
resolved(result);
})
.catch(function(error) {
debug( 'fail to discover resource('+type+') information ' + error );
rejected(error);
});
});
}
/**
* @method DiscoverDirectChildResource Get Direct Child Resources
* @param {string} resourceUrl Parent URL : (server_address/mp_url/cb/ae?/cnt?)
* @param {string} origin requester, default 'SOrigin'
* @param {Array<number>} contentModel types array
* @returns {Promise}
*/
function DiscoverDirectChildResource(resourceUrl, origin, contentModel) {
origin = fnDefaultOrigin(origin);
debug( 'DiscoverDirectChildResource is called with url: ' + resourceUrl + ', origin: ' + origin + ', contentModel: ' + contentModel );
return new Promise(function(resolved, rejected) {
var needGetCin = false;
var filterCriteria = '?rcn=4&lvl=1';
contentModel.map(function(item){
if(item=='4') { // cin
needGetCin = true;
}
else {
filterCriteria += ('&ty=' + item);
}
});
var options = {
method: 'GET',
uri: resourceUrl + filterCriteria,
headers: {
"Accept": "application/json",
"nmtype": "short",
"X-M2M-RI": Uuid.v4(),
"X-M2M-Origin": origin
},
json: true
};
debug( "DISCOVER : " + resourceUrl + filterCriteria);
Http(options)
.then(function(result) {
resolved(result);
})
.catch(function(error) {
rejected(error);
});
});
}
/**
* @method DiscoverChildInstance Get the Children Resource at the set Level
* @param {string} resourceUrl Parent URL like (server_address/mp_url/cb/ae?/cnt?)
* @param {string} origin requester default 'SOrigin'
* @param {number|Array<number>} type type of resource
* @param {number} limit MAX value getting resources, Default 5
* @param {number} level Depth Level, Default 1
* @returns {Promise}
*/
function DiscoverChildInstance(resourceUrl, origin, type, limit, level) {
origin = fnDefaultOrigin(origin);
debug( 'DiscoverChildInstance is called with url: ' + resourceUrl + ', origin: ' + origin + ', type: ' + type + ', limit: ' + limit );
return new Promise(function(resolved, rejected) {
var needGetCin = false;
var filterCriteria = '?rcn=4';
// set level
filterCriteria += "&lvl=" + (level ? level : 1);
// set type
if( type ){
if(type instanceof Array){
type.forEach((ty)=> {
filterCriteria += '&ty=' + ty;
})
}else{
filterCriteria += '&ty=' + type;
}
}
filterCriteria += ('&la=' + CONFIG.limit);
var options = {
method: 'GET',
uri: resourceUrl + filterCriteria,
headers: {
"Accept": "application/json",
"nmtype": "short",
"X-M2M-RI": Uuid.v4(),
"X-M2M-Origin": origin
},
json: true
};
debug( "DISCOVER : " + resourceUrl + filterCriteria);
Http(options)
.then(function(result) {
resolved(result);
})
.catch(function(error) {
rejected(error);
});
});
}
/**
* @method DeleteResource NOTICE, origin have to be equal creation's origin
* @param {string} resourceUrl URL like (server_address/mp_url/cb/ae?/cnt?)
* @param {string} origin Resource's RI
* @returns {Promise}
*/
function DeleteResource(resourceUrl, origin) {
if(!resourceUrl || resourceUrl.length < 1){
throw new Error("resourceUrl is unusable data! please check your resourceUrl");
}
origin = fnDefaultOrigin(origin);
debug( 'DeleteResource is called with url: ' + resourceUrl + ', origin: ' + origin);
return new Promise(function(resolved, rejected) {
var options = {
method: 'DELETE',
uri: resourceUrl,
headers: {
"Accept": "application/json",
"nmtype": "short",
"X-M2M-RI": Uuid.v4(),
"X-M2M-Origin": origin
},
json: true
};
Http(options)
.then(function(result) {
debug( 'success to delete resource information ' + result );
resolved(result);
})
.catch(function(error) {
debug( 'fail to delete resource information ' + error );
rejected(error);
});
});
}
/**
* @method CreateResource NOTICE, resource has individual difference property by types
* @param {string} parentResourceUrl URL like (server_address/mp_url/cb/ae?/cnt?)
* @param {Object} resource Object by types
* @param {string} origin requester default 'SOrigin'
* @returns {Promise}
*/
function CreateResource(parentResourceUrl, resource, origin) {
if(!parentResourceUrl || parentResourceUrl.length < 1){
throw new Error("parentResource is unusable data! please check your parentResource");
}else if(!resource) {
throw new Error("resource is unusable data! please check your resource");
}
origin = fnDefaultOrigin(origin);
return new Promise(function(resolved, rejected) {
var resourceType = _.keys(resource)[0];
var resourceTypeCode = onem2mModel.Resource.getTypeCode(resourceType);
var options = {
method: 'POST',
uri: parentResourceUrl,
headers: {
"Accept": "application/json",
"Content-Type": "application/vnd.onem2m-res+json;ty="+resourceTypeCode,
"X-M2M-RI": Uuid.v4(),
"X-M2M-Origin": origin
},
body: resource,
json: true,
time: true,
resolveWithFullResponse: true
};
Http(options)
.then(function(result) {
debug( 'success to create resource ' + result );
result = result.body;
resolved(result);
})
.catch(function(error) {
debug( 'fail to create resource ' );
debug( error.message );
rejected(error);
});
});
}
/**
* @typedef {Object} subscribeOptions
* @property {Array<Number>|number} ty
* @property {Array<Number>|number} enc
* - 1 : resource's infomation was modified
* - 2 : resource was removed
* - 3 : resource's child was created
* - 4 : resource's cihld was removed
* @property {Number} exc
* - '0' does mean infinite
*/
/**
*
* @param {String} resourceUrl
* @param {String} subscriptionName
* @param {String} origin
* @param {String} mqttBrokerUrl
* @param {subscribeOptions} options
* @returns {Promise}
*/
function SubscribeTo(parentResourceUrl, subscriptionName, origin, mqttBrokerUrl, options){
if(!parentResourceUrl){
throw new Error("parentResourceUrl is necessary property");
}else if(!subscriptionName || subscriptionName == ""){
subscriptionName = CONFIG.sub.name;
}else if(!mqttBrokerUrl){
throw new Error("mqttBrokerUrl is necessary property");
}else if(options){
_.extend(CONFIG.sub, options);
}
origin = fnDefaultOrigin(origin);
var resource = {
'm2m:sub' : {
'rn': subscriptionName,
'enc': {
'net': CONFIG.sub.enc
},
'exc' : CONFIG.sub.exc,
'nu': [mqttBrokerUrl]
}
};
return new Promise((resolve, reject)=>{
CreateResource(parentResourceUrl, resource, origin)
.then((res)=>{
resolve(res);
})
.catch((err)=>{
if(err.statusCode == 409){
console.log(`try delete existed subscription : ${parentResourceUrl}/${subscriptionName}`);
DeleteResource(`${parentResourceUrl}/${subscriptionName}`, origin)
.then(() =>{
return CreateResource(parentResourceUrl, resource, origin);
})
.then((res2)=>{
resolve(res2);
})
.catch((err)=>{
reject(err);
})
}else{
reject(err);
}
})
})
}
/**
*
* @param {String} parentResourceUrl
* @param {String} subscriptionName
* @param {String} origin
* @returns {Promise}
*/
function UnSubscribeFrom(parentResourceUrl, subscriptionName, origin){
if(!parentResourceUrl || parentResourceUrl.length < 1){
throw new Error("parentResourceUrl is necessary property");
}else if(!subscriptionName || subscriptionName.length < 1){
subscriptionName = CONFIG.sub.name;
}
origin = fnDefaultOrigin(origin);
var subScriptionUrl = `${parentResourceUrl}/${subscriptionName}`;
return new Promise((resolve, reject) => {
DeleteResource(subScriptionUrl, origin)
.then( res => {
resolve(res);
})
.catch( err => {
reject(err);
})
})
}
function fnDefaultOrigin(origin){
return (origin && origin.length > 0) ? origin : CONFIG.origin;
}
}