osif-client
Version:
KOREA Electronics Technology Institute(KETI) provides a OSIF client library for the project called Cognitive IoT R&D Project.
806 lines (653 loc) • 19.2 kB
JavaScript
/**
* Created by TaeHyun KIM @ SyncTechno.com on 2017. 7. 14.
*
* This project is supported by KETI Cognitive IoT Project.
*/
var HazelcastClient = require('hazelcast-client').Client
, Config = require('hazelcast-client').Config
, uuidv4 = require('uuid/v4')
, debug = require('debug')('osif')
;
var RESERVED_KEY = {
"OSIF_DEVICE_INFO": "OSIF_DEVICE_INFO",
"OSIF_LOCAL_OPENDATA": "OSIF_LOCAL_OPENDATA",
"OSIF_RUNNING_DEVICE": "OSIF_RUNNING_DEVICE",
"OSIF_RUNNING_SERVICE": "OSIF_RUNNING_SERVICE",
"OSIF_GLOBAL_OPENDATA": "OSIF_GLOBAL_OPENDATA",
"OSIF_DEVICE_ID": "OSIF_DEVICE_ID",
"CIOT_APP_MANAGER_REQ": "CIOT_APP_MANAGER_REQ",
"CIOT_OPENDATA_LIST": "CIOT_OPENDATA_LIST"
};
OsifClient.RESERVED_KEY = RESERVED_KEY;
/**
*
*
* @param options
* {
* "service": {
* "serviceId": 'uuid',
* "serviceName": 'service name',
* "serviceDesc": 'description text for service',
* "versionCode": {
* major: 1, minor: 1, revision:1
* },
* "openData": {
* "local": [{
* "name": "open data name",
* "description": "data description",
* "template": "descriptive text for format of open data contents"
* }],
* "global: [{
* "name": "open data name",
* "description": "data description",
* "template": "descriptive text for format of open data contents"
* }]
* }
* }
*
* "databus": {
* "globalHost": "ip.address.of.cloud",
* "globalPort": "port",
* "localPort": "port"
* }
* }
*
*/
function OsifClient(options) {
/**
* Options
*/
options = options || {};
try {
_assertProperty(options.service.serviceName, 'options.service.serviceName');
_assertProperty(options.service.serviceId, 'options.service.serviceId');
_assertProperty(options.service.versionCode, 'options.service.versionCode');
_assertProperty(options.databus.globalHost, 'options.databus.globalHost');
_assertProperty(options.databus.globalPort, 'options.databus.globalPort');
_assertProperty(options.databus.localPort, 'options.databus.localPort');
options.databus['localHost'] = '127.0.0.1'; // default
options.databus['group'] = {
'name': 'osif',
'password': 'osif-pass'
};
} catch (ex) {
debug( ex );
throw Error('Failed on creating new OsifClient object: missing required options');
}
/**
* Member Variables
*
*/
this.databus = options.databus;
this.service = options.service;
this.service.instanceId = options.service.serviceId || uuidv4();
this.subscriptionList = {
"global": {},
"local": {}
};
this.clientInitialized = false;
}
/**
* Member Functions
*
*/
OsifClient.prototype.init = _initClient;
OsifClient.prototype.startService = _startService;
OsifClient.prototype.stopService = _stopService;
OsifClient.prototype.readDeviceId = _readDeviceId;
OsifClient.prototype.registerServiceInstanceInfo = _registerServiceInstanceInfo;
OsifClient.prototype.unregisterServiceInstanceInfo = _unregisterServiceInstanceInfo;
// read and write my service data
OsifClient.prototype.setGlobalAppData = _setGlobalAppData;
OsifClient.prototype.getGlobalAppData = _getGlobalAppData;
OsifClient.prototype.setLocalAppData = _setLocalAppData;
OsifClient.prototype.getLocalAppData = _getLocalAppData;
// read open data which is owned by other service
OsifClient.prototype.getGlobalOpendata = _getGlobalOpendata;
OsifClient.prototype.getLocalOpendata = _getLocalOpendata;
// subscribe/unsubscribe to open data which is owned by other service
OsifClient.prototype.subscribeToLocalOpendata = _subscribeToLocalOpendata;
OsifClient.prototype.unsubscribeToLocalOpendata = _unsubscribeToLocalOpendata;
OsifClient.prototype.subscribeToGlobalOpendata = _subscribeToGlobalOpendata;
OsifClient.prototype.unsubscribeToGlobalOpendata = _unsubscribeToGlobalOpendata;
/**
* Implementations of Private functions for internal use.
*/
function _assert(condition, message) {
if (!condition) {
throw message || "Assertion failed";
}
}
function _assertProperty(condition, message) {
if (typeof condition === 'undefined') {
throw message || "Assertion failed";
}
}
function _createHazelcastClient(host, port, group) {
console.log( host, port, group);
return new Promise(function (resolve, reject) {
try {
var config = new Config.ClientConfig();
config.networkConfig.addresses = [{
host: host,
port: port
}];
if(group)
config.groupConfig = group;
HazelcastClient.newHazelcastClient(config)
.then(function(hazelcastClient){
resolve(hazelcastClient)
})
.catch(function(err){
debug('error:', host, port);
reject(err);
});
}
catch (ex) {
debug( ex );
reject(ex);
}
});
}
function _readDeviceId() {
var thisObj = this;
return new Promise((resolve, reject)=>{
try {
var deviceInfoMap = thisObj.localDatabusClient.getMap(RESERVED_KEY.OSIF_DEVICE_INFO);
deviceInfoMap.get(RESERVED_KEY.OSIF_DEVICE_ID)
.then((deviceId)=>{
console.log( "DEVICE ID", deviceId);
resolve(deviceId);
})
.catch((err)=>{
reject(err);
});
}
catch(ex) {
debug('EXCEPTION:', ex);
reject(ex);
}
});
}
function _registerServiceInstanceInfo() {
var thisObj = this;
return new Promise((resolve, reject) => {
try {
// register running service info. to global data grid
console.log( "set running service map:", thisObj.runningServiceId);
thisObj.runningServiceMap.set(thisObj.runningServiceId, thisObj.service)
.then(()=>{
var openDataList = [];
if(thisObj.service.openData && thisObj.service.openData.local) {
thisObj.service.openData.local.map((item)=>{
if(item.name)
openDataList.push(item.name);
});
}
if(openDataList.length > 0) {
return Promise.all(
openDataList.map((item)=>{
var openDataName = thisObj.runningServiceId + '#' + item;
return thisObj.localOpenDataMap.set(openDataName, '');
})
);
}
else {
return [];
}
})
.then((result)=>{
var openDataList = [];
if(thisObj.service.openData && thisObj.service.openData.global) {
thisObj.service.openData.global.map((item)=>{
if(item.name)
openDataList.push(item.name);
});
}
if(openDataList.length > 0) {
return Promise.all(
openDataList.map((item)=>{
var openDataName = thisObj.runningServiceId + '#' + item;
return thisObj.globalOpenDataMap.set(openDataName, '');
})
);
}
else {
return [];
}
})
.then((result)=>{
resolve(thisObj);
})
.catch((err)=>{
debug('ERROR:', err);
reject(err);
})
}
catch (ex) {
debug('EXCEPTION:', ex);
reject(ex);
}
});
}
function _unregisterServiceInstanceInfo() {
var thisObj = this;
return new Promise((resolve, reject) => {
try {
// register running service info. to global data grid
thisObj.runningServiceMap.delete(thisObj.runningServiceId)
.then(()=>{
var openDataList = [];
if(thisObj.service.openData && thisObj.service.openData.local) {
thisObj.service.openData.local.map((item)=>{
if(item.name)
openDataList.push(item.name);
});
}
if(openDataList.length > 0) {
return Promise.all(
openDataList.map((item)=>{
var openDataName = thisObj.runningServiceId + '#' + item;
return thisObj.localOpenDataMap.delete(openDataName);
})
);
}
else {
return [];
}
})
.then((result)=>{
var openDataList = [];
if(thisObj.service.openData && thisObj.service.openData.global) {
thisObj.service.openData.global.map((item)=>{
if(item.name)
openDataList.push(item.name);
});
}
if(openDataList.length > 0) {
return Promise.all(
openDataList.map((item)=>{
var openDataName = thisObj.runningServiceId + '#' + item;
return thisObj.globalOpenDataMap.delete(openDataName);
})
);
}
else {
return [];
}
})
.then((result)=>{
resolve(thisObj);
})
.catch((err)=>{
debug('ERROR:', err);
reject(err);
})
}
catch (ex) {
debug('EXCEPTION:', ex);
reject(ex);
}
});
}
/**
* Implementations of Member Functions
*
*/
function _initClient() {
var thisObj = this;
return new Promise(function (resolve, reject) {
try {
if (thisObj.clientInitialized)
resolve(thisObj);
else {
_createHazelcastClient(thisObj.databus.globalHost, thisObj.databus.globalPort, thisObj.databus.group)
.then(function(globalDatabusClient){
thisObj.globalDatabusClient = globalDatabusClient;
return _createHazelcastClient(thisObj.databus.localHost, thisObj.databus.localPort)
})
.then(function(localDatabusClient) {
thisObj.localDatabusClient = localDatabusClient;
return thisObj.readDeviceId();
})
.then((deviceId)=> {
thisObj.deviceId = deviceId;
//thisObj.runningServiceId = [deviceId, thisObj.service.serviceName].join('#');
thisObj.runningServiceId = thisObj.service.serviceId;
thisObj.runningServiceMap = thisObj.globalDatabusClient.getMap(RESERVED_KEY.OSIF_RUNNING_SERVICE);
thisObj.globalOpenDataMap = thisObj.globalDatabusClient.getMap(RESERVED_KEY.OSIF_GLOBAL_OPENDATA);
thisObj.localOpenDataMap = thisObj.localDatabusClient.getMap(RESERVED_KEY.OSIF_LOCAL_OPENDATA);
thisObj.clientInitialized = true;
resolve(thisObj);
})
.catch(function(err){
debug( err );
reject(err);
});
}
}
catch (ex) {
debug( ex );
reject(ex);
}
});
}
function _startService() {
var thisClient = this;
return new Promise(function(resolve, reject){
try {
thisClient.init()
.then((client)=> {
// register service info to Global.OSIF_RUNNING_DEVICE
return thisClient.registerServiceInstanceInfo();
})
.then((client)=>{
resolve(thisClient);
})
.catch(function(err){
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _stopService() {
var thisClient = this;
return new Promise(function(resolve, reject){
try {
thisClient.init()
.then((client)=> {
return thisClient.unregisterServiceInstanceInfo();
})
.then((client)=>{
resolve(client);
})
.catch((err)=>{
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _setGlobalAppData(key, value) {
var thisClient = this;
return new Promise(function (resolve, reject) {
try {
var dataInfo = thisClient.service.openData.global.find((item)=>{
if(item.name == key)
return true;
else
return false;
});
if(!dataInfo)
throw new Error('Illegal argument');
thisClient.init()
.then(function(thisClient){
var key = thisClient.runningServiceId + "#" + dataInfo.name;
console.log('SET GLOBAL APP DATA:', key, value );
return thisClient.globalOpenDataMap.set(key, value);
})
.then(function(result){
resolve(value);
})
.catch(function (err) {
debug(err);
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _setLocalAppData(key, value) {
var thisClient = this;
return new Promise(function (resolve, reject) {
try {
var dataInfo = thisClient.service.openData.local.find((item)=>{
if(item.name == key)
return true;
else
return false;
});
if(!dataInfo)
throw new Error('Illegal argument');
thisClient.init()
.then(function(thisClient){
var key = thisClient.runningServiceId + "#" + dataInfo.name;
return thisClient.localOpenDataMap.set(key, value);
})
.then(function(result){
resolve(value);
})
.catch(function (err) {
debug(err);
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _getGlobalAppData(key) {
var thisClient = this;
return new Promise(function (resolve, reject) {
try {
var dataInfo = thisClient.service.openData.global.find((item)=>{
if(item.name == key)
return true;
else
return false;
});
if(!dataInfo)
throw new Error('Illegal argument');
thisClient.init()
.then(function(thisClient){
var key = thisClient.runningServiceId + "#" + dataInfo.name;
return thisClient.globalOpenDataMap.get(key);
})
.then(function(result) {
resolve(result);
})
.catch(function (err) {
debug(err);
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _getLocalAppData(key) {
var thisClient = this;
return new Promise(function (resolve, reject) {
try {
var dataInfo = thisClient.service.openData.local.find((item)=>{
if(item.name == key)
return true;
else
return false;
});
if(!dataInfo)
throw new Error('Illegal argument');
thisClient.init()
.then(function(thisClient){
var key = thisClient.runningServiceId + "#" + dataInfo.name;
return thisClient.localOpenDataMap.get(key);
})
.then(function(result) {
resolve(result);
})
.catch(function (err) {
debug(err);
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _getGlobalOpendata(serviceId, name) {
var thisClient = this;
return new Promise(function (resolve, reject) {
try {
thisClient.init()
.then(function(thisClient){
var key = serviceId + "#" + name;
return thisClient.globalOpenDataMap.get(key);
})
.then(function(result) {
resolve(result);
})
.catch(function (err) {
debug(err);
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _getLocalOpendata(serviceId, key) {
var thisClient = this;
return new Promise(function (resolve, reject) {
try {
thisClient.init()
.then(function(thisClient){
var key = serviceId + "#" + name;
return thisClient.localOpenDataMap.get(key);
})
.then(function(result) {
resolve(result);
})
.catch(function (err) {
debug(err);
reject(err);
});
}
catch(ex) {
debug(ex);
reject(ex);
}
});
}
function _subscribeToGlobalOpendata(serviceId, key, listener) {
var thisClient = this;
var openDataKey = serviceId + "#" + key;
return new Promise(function (resolve, reject) {
try {
thisClient.init()
.then(function (thisClient) {
if(thisClient.globalOpenDataMap) {
var listenerList = thisClient.subscriptionList.global[openDataKey];
if(typeof listenerList === 'undefined') {
listenerList = [];
thisClient.subscriptionList.global[openDataKey] = listenerList;
}
if( listenerList.indexOf(listener) == -1 ) {
listenerList.push(listener);
var listenerObj = {
'updated': listener,
'added': listener
};
console.log( "LISTEN TO: ", openDataKey );
thisClient.globalOpenDataMap.addEntryListener(listenerObj, openDataKey, true)
.then(function(result) {
resolve(result);
})
.catch(function(err) {
debug(err);
reject(err);
} );
}
else {
resolve(thisClient);
}
}
else {
throw new Error('Cannot access global open data');
}
})
.catch(function (err) {
debug( err );
reject(err);
});
}
catch (ex) {
debug( ex );
reject(ex);
}
});
}
function _subscribeToLocalOpendata(key, listener) {
var thisClient = this;
var openDataKey = serviceId + "#" + key;
return new Promise(function (resolve, reject) {
try {
thisClient.init()
.then(function (thisClient) {
if(thisClient.localOpenDataMap) {
var listenerList = thisClient.subscriptionList.local[openDataKey];
if(typeof listenerList === 'undefined') {
listenerList = [];
thisClient.subscriptionList.local[openDataKey] = listenerList;
}
if( listenerList.indexOf(listener) == -1 ) {
listenerList.push(listener);
var listenerObj = {
'updated': listener,
'added': listener
};
thisClient.localOpenDataMap.addEntryListener(listenerObj, openDataKey, true)
.then(function(result) {
resolve(result);
})
.catch(function(err) {
debug(err);
reject(err);
} );
}
else {
resolve(thisClient);
}
}
else {
throw new Error('Cannot access local open data');
}
})
.catch(function (err) {
debug( err );
reject(err);
});
}
catch (ex) {
debug( ex );
reject(ex);
}
});
}
function _unsubscribeToGlobalOpendata(key, listener) {
throw new Error('not implemented yet');
}
function _unsubscribeToLocalOpendata(key, listener) {
throw new Error('not implemented yet');
}
/**
* Expose 'OsifClient'
*/
module.exports = OsifClient;