jchaos
Version:
module to access chaos resources
1,296 lines (1,158 loc) • 185 kB
JavaScript
/**
* !CHAOS REST Library
*@fileOverview
*@version 1.1.92
*@author Andrea Michelotti
*@module jchaos
*/
/**
* Callback in asynchronous operations called when the operation is ok
* @callback okcb
* @param {object} data depend on the operation (typically a dataset)
*/
/**
* Callback in asynchronous operations called when the operation is fails
* @callback badcb
* @param {string|object} data description of the error
*/
/**
* The command object for sendCU commands
* @typedef {Object} cmdPar
* @property {string} cmd - command name
* @property {integer} prio - Priority
* @property {integer} mode - mode
*/
/**
* CU variable path
* @typedef {Object} varpath
* @property {string} cu CU PATH
* @property {string} dir direction (input,output)
* @property {string} var variable dataset name
* @property {string} const constantco:String
* @property {string} origin full path
*/
/**
* Channel identification mapping:
* -1 : all
* 0: output
* 1: input
* 2: custom
* 3: system
* 4: health
* 5: cu alarms
* 6: device alarms
* 128: status
* 255: health+system+ alarams
* @typedef {integer} channelid
*/
/**
* @typedef ChaosOption
* @type {object}
* @property {boolean} updateEachCall history update each call
* @property {string} uri address:port of the REST server
*/
(function () {
/**
* Creates a new jchaos object.
* @class
*/
function createLibrary() {
var jchaos = {};
jchaos['latency'] = 0;
jchaos['latency_avg'] = 0;
jchaos['latency_tot'] = 0;
jchaos['errors'] = 0;
jchaos['timeouts'] = 0;
jchaos['nops'] = 0;
jchaos['logops_enable'] = false;
jchaos['maxlogops'] = 100;
jchaos['ops_list'] = [];
jchaos['numok'] = 0;
jchaos['implementation_map'] = { "powersupply": ["SCPowerSupply", "RTMG1PowerSupply"], "motor": ["SCActuator"], "camera": ["RTCamera", "cameraGFIT"], "bpm": ["SCLibera"] };
jchaos.extendJson = function (key, n) {
// Filtraggio delle proprietà
if (Number(n) === n && n % 1 !== 0) {
var obj = { $numberDouble: n.toString() };
return obj;
}
return n;
}
jchaos.logops = function (request, logop) {
var enable = logop || jchaos['logops_enable'];
if (enable) {
request['jchaos_status'] = request.status;
if (jchaos['ops_list'].length < jchaos['maxlogops']) {
jchaos['ops_list'].push(JSON.stringify(request));
} else {
jchaos['ops_list'].shift();
jchaos['ops_list'].push(JSON.stringify(request));
}
}
}
jchaos.channelToString = function (id) {
switch (id) {
case 0:
return "output";
case 1:
return "input";
case 2:
return "custom";
case 3:
return "system";
case 4:
return "health";
case 5:
return "device_alarms";
case 6:
return "cu_alarms";
case 7:
return "log";
default:
return "UKNOWN CHANNEL"
}
}
jchaos.extendStringKey = function (obj, key) {
if (obj.hasOwnProperty(key) && (typeof obj[key] === "string")) {
try {
var o = JSON.parse(obj[key]);
obj[key] = JSON.stringify(o, jchaos.extendJson);
} catch (e) {
}
return obj;
}
// Filtraggio delle proprietà
if (Number(n) === n && n % 1 !== 0) {
var obj = { $numberDouble: n.toString() };
return obj;
}
return n;
}
jchaos.ops_on_going = 0;
jchaos.ops_abort = false;
jchaos.lastChannel = {};
/**
* @prop {boolean} updateEachCall=true choose if update each call of history operation
* @prop {string} uri=localhost:8081 REST server URI
* @prop {boolean} async=true if false force the call to be synchronous, otherwise depend if the callback is definedd
* @prop {integer} limit_on_going=10000 limits the concurrent operations
* @prop {integer} history_page_len=1000 default history page len
* @prop {integer} timeout=5000 default timeout for operation
* @prop {callback} console_log redirected on console.log
* @prop {callback} console_err redirected on console.error
*/
jchaos.socket = null;
jchaos.options = {
updateEachCall: false,
uri: "http://localhost:8081",
socketio: { url: "ws://localhost:4000", opt: {} },
async: true,
limit_on_going: 10000,
history_page_len: 1000,
timeout: 10000,
console_log: function (str) { console.log(str); },
console_err: function (str) { console.error(str); },
io_onconnect: function (sock) { console.log("Connected to " + jchaos.options['socketio'] + " id:" + sock.id); },
io_disconnect: function (sock) { console.log("Disconnected from:" + jchaos.options['socketio'] + " id:" + sock.id); },
io_onmessage: function (msg) { console.log("incoming kafka message without handler, unsubscribe all"); },
io_onerror: function (msg) { console.log("Error: " + JSON.stringify(msg)); },
io_onchat: function (msg) { console.log("Chat: " + msg); },
on_restTimeout: function (msg) { jchaos.perror("Timeout:" + msg); },
on_restOk: function (msg) { },
io_heartbeat: 0
};
jchaos.ioconnect = function (uri, opt) {
var ws = uri || jchaos.options['socketio'].url;
jchaos.options['socketio'] = ws;
if (opt === undefined) {
opt = {};
}
opt['transports'] = ['websocket'];
jchaos.socket = io(ws, opt);
jchaos.socket.on("connect", () => {
jchaos.options.io_onconnect(jchaos.socket);
jchaos.options.io_heartbeat = setInterval(function () {
jchaos.socket.emit('heartbeat', { data: jchaos.getDateTime() });
}, 60000);
});
jchaos.socket.on("connect_error", () => {
jchaos.options.io_onerror("Connection error:" + jchaos.options['socketio']);
});
jchaos.socket.on("disconnect", () => {
jchaos.options.io_disconnect(jchaos.socket);
clearInterval(jchaos.options.io_heartbeat);
});
jchaos.socket.on("msg", (msg) => {
jchaos.options.io_onmessage(msg);
});
jchaos.socket.on("chaos_web_log", (msg) => {
try {
jchaos.options.io_onchat(JSON.parse(msg));
jchaos.print("Server message :'" + msg + "'");
} catch (e) {
jchaos.perror("error parsing message :'" + JSON.stringify(msg) + "' error:" + e);
}
});
jchaos.socket.on("error", (msg) => {
jchaos.options.io_onerror(msg);
});
}
jchaos.iomessage = function (msg, user, type, dst) {
var nmesg = {};
if (typeof msg === "object") {
nmesg = msg;
} else {
if ((typeof msg !== "string") || (msg == "")) {
jchaos.perror("empty messages not allowed");
return;
}
nmesg['username'] = user;
nmesg['msg'] = msg || "";
nmesg['type'] = type || "user";
}
nmesg['date'] = jchaos.getDateTime();
nmesg['dst'] = dst || "broadcast";
nmesg['src'] = location.host;
jchaos.print("sending:" + JSON.stringify(nmesg));
jchaos.socket.emit("chaos_web_log", nmesg);
}
jchaos.chaosDatasetToFullDS = function (ds) {
var obj = {};
if (ds.dpck_ds_type == 0) {
obj['output'] = ds;
} else if (ds.dpck_ds_type == 1) {
obj['input'] = ds;
} else if (ds.dpck_ds_type == 2) {
obj['custom'] = ds;
} else if (ds.dpck_ds_type == 3) {
obj['system'] = ds;
} else if (ds.dpck_ds_type == 4) {
obj['health'] = ds;
}
if (ds.dpck_ds_type == 5) {
obj['device_alarms'] = ds;
} else if (ds.dpck_ds_type == 6) {
obj['cu_alarms'] = ds;
} else if (ds.dpck_ds_type == 7) {
obj['log'] = ds;
}
return obj;
}
jchaos.ioclose = function () {
console.log("Closing I/O");
jchaos.socket.emit("close", "all");
// jchaos['io_onconnect']=(sock)=> {console.log("Connected to "+jchaos.options['socketio']+" id:"+sock.id);};
// jchaos['io_disconnect']=(sock)=> {console.log("Disconnected from:"+jchaos.options['socketio']+" id:"+sock.id);};
jchaos['io_onmessage'] = (msg) => { console.log("incoming kafka message "); }
}
jchaos.unsubscribeall=function(){
jchaos.iosubscribeCU("all",false);
}
/**
* Subscribe/unsubscribe a list of CU with their dataset
* @param {array} culist list of cu
* @param {boolean} subscribe true to subscribe,false to unsubscribe
* @param {array} chans array of channels if not defined all channels.
*/
jchaos.iosubscribeCU = function (culist, subscribe, opt) {
var topics = [];
var options={}
if(typeof opt==="object"){
options=opt;
}
if ((typeof culist === "string")) {
if ((culist == "all")) {
if ((subscribe !== undefined) && (subscribe == false)) {
jchaos.socket.emit("unsubscribeall", "");
return;
}
} else {
culist = [culist];
}
}
topics = jchaos.keysToTopic(culist);
options['topics']=topics;
if (subscribe !== undefined && (subscribe === false)) {
jchaos.socket.emit("unsubscribe", JSON.stringify(options));
} else {
jchaos.socket.emit("subscribe", JSON.stringify(options));
}
}
/**
* Return an object with the zone, group and uid of the path
* return null if not valid
* @param {string} cupath
*/
jchaos.pathToZoneGroupId = function (cupath) {
var regex = /(.*)\/(.*)\/(.*)$/;
var match = regex.exec(cupath);
if (match != null) {
return { 'zone': match[1], 'group': match[2], 'id': match[3] };
}
return null
}
jchaos.getDateTime = function (t) {
if (typeof t === "string") {
t = parseInt(t);
return new Date(t).toLocaleString('it-IT', { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' });
} else if (typeof t === "number") {
return new Date(t).toLocaleString('it-IT', { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' });
}
return new Date().toLocaleString('it-IT', { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' });
}
jchaos.keysToTopic = function (arr, postfix) {
var ret = [];
arr.forEach(elem => {
if (typeof postfix === "string") {
ret.push(elem.replaceAll('/', '.') + postfix);
} else {
ret.push(elem.replaceAll('/', '.'));
}
})
return ret;
}
jchaos.generateUID = function () {
var dt = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (dt + Math.random() * 16) % 16 | 0;
dt = Math.floor(dt / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
/**
* Decode a CU dataset element path and return an object
* @param {string} cupath
* @function decodeCUPath
* @return {varpath}
*/
jchaos.decodeCUPath = function (cupath) {
var regex_vect = /(.*)\/(.*)\/(.*)\[([-\d]+)\]$/;
var regex = /(.*)\/(.*)\/(.*)$/;
var tmp = {
cu: null,
dir: null,
var: null,
const: null,
origin: cupath
};
if ($.isNumeric(cupath)) {
tmp = {
cu: null,
dir: null,
var: null,
const: Number(cupath),
index: null, // in case of vectors
origin: cupath
};
return tmp;
}
var match = regex_vect.exec(cupath);
if (match != null) {
tmp = {
cu: match[1],
dir: match[2],
var: match[3],
const: null,
index: match[4],
origin: cupath
};
return tmp;
}
match = regex.exec(cupath);
if (match != null) {
tmp = {
cu: match[1],
dir: match[2],
var: match[3],
const: null,
index: null,
origin: cupath
};
} else if ((match = /(.*)\/(.*)/.exec(cupath))) {
tmp = {
cu: match[1],
dir: "",
var: match[2],
const: null,
index: null,
origin: cupath
};
}
return tmp;
}
jchaos.jsonDiff = function (ob1, ob2) {
var deepDiffMapper = function () {
return {
VALUE_CREATED: 'created',
VALUE_UPDATED: 'updated',
VALUE_DELETED: 'deleted',
VALUE_UNCHANGED: 'unchanged',
map: function (obj1, obj2) {
if (this.isFunction(obj1) || this.isFunction(obj2)) {
throw 'Invalid argument. Function given, object expected.';
}
if (this.isValue(obj1) || this.isValue(obj2)) {
if (this.compareValues(obj1, obj2) == this.VALUE_UPDATED) {
return (obj1 === undefined) ? obj2 : obj1
} else {
return null;
}
}
var diff = {};
for (var key in obj1) {
if (this.isFunction(obj1[key])) {
continue;
}
var value2 = undefined;
if (obj2[key] !== undefined) {
value2 = obj2[key];
}
var o = this.map(obj1[key], value2);
if ((o != null) && (JSON.stringify(o) !== "{}")) {
diff[key] = o;
}
}
for (var key in obj2) {
if (this.isFunction(obj2[key]) || diff[key] !== undefined) {
continue;
}
var o = this.map(undefined, obj2[key]);
if ((o != null) && (JSON.stringify(o) !== "{}")) {
diff[key] = o;
}
}
return diff;
},
compareValues: function (value1, value2) {
if (value1 === value2) {
return this.VALUE_UNCHANGED;
}
if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) {
return this.VALUE_UNCHANGED;
}
if (value1 === undefined) {
return this.VALUE_CREATED;
}
if (value2 === undefined) {
return this.VALUE_DELETED;
}
return this.VALUE_UPDATED;
},
isFunction: function (x) {
return Object.prototype.toString.call(x) === '[object Function]';
},
isArray: function (x) {
return Object.prototype.toString.call(x) === '[object Array]';
},
isDate: function (x) {
return Object.prototype.toString.call(x) === '[object Date]';
},
isObject: function (x) {
return Object.prototype.toString.call(x) === '[object Object]';
},
isValue: function (x) {
return !this.isObject(x) && !this.isArray(x);
}
}
}();
return deepDiffMapper.map(ob1, ob2);
}
jchaos.isCollapsable = function (arg) {
return arg instanceof Object && Object.keys(arg).length > 0;
}
/**
* translate seconds in days hours minutes seconds string
* @function toHHMMSS
* @param {integer} sec_num
* @return {string} return string xx days hh:mm:ss
*/
jchaos.toHHMMSS = function (sec_num) {
// var sec_num = parseInt(this, 10); // don't forget the second param
var days = Math.floor(sec_num / 86400);
var hours = Math.floor((sec_num - (days * 86400)) / 3600);
var minutes = Math.floor((sec_num - (days * 86400) - (hours * 3600)) / 60);
var seconds = sec_num - (days * 86400) - (hours * 3600) - (minutes * 60);
if (days < 10) {
days = "0" + days;
}
if (hours < 10) {
hours = "0" + hours;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
return days + ' days ' + hours + ':' + minutes + ':' + seconds;
}
/********** */
class ChaosNode {
syncDesc() {
var prom = new Promise((resolve, reject) => {
jchaos.node(this.uid, "desc", "all", (data) => {
this.desc = data;
resolve(this.desc);
}, (bad) => { reject(bad); });
});
return prom;
}
syncDS() {
var prom = new Promise((resolve, reject) => {
jchaos.getChannel(this.uid, -1, (data) => {
this.ds = data[0];
/* this.ds['output'] = data[0];
this.ds['input'] = data[1];
this.ds['custom'] = data[2];
this.ds['system'] = data[3];
this.ds['health'] = data[4];
this.ds['calarm'] = data[5];
this.ds['dalarm'] = data[6];*/
resolve(this.ds);
}, (bad) => { reject(bad); });
});
return prom;
}
constructor(uid, okfn, badfn) {
this.uid = uid;
this.storage = 2; // live
this.ds = {};
this.desc = {};
this.methods = [];
console.log("Chaos Node " + uid);
this.syncDS().then((ok) => {
var prom = this.syncDesc();
prom.then((d) => {
var promise =
import('./interface/' + this.impl() + ".js");
promise.then((obj) => {
console.log("Adding interface " + this.impl());
if (typeof obj === "object") {
for (var k in obj) {
if (typeof obj[k] === "function") {
this.__proto__[k] = obj[k];
} else {
this[k] = obj[k];
}
}
}
if (typeof okfn === "function") {
okfn(this);
}
}).catch(err => {
jchaos.perror("error:" + err.message);
if (typeof badfn === "function") {
badfn(err);
}
});
});
return prom;
}, (bad) => { console.error("DS error:" + JSON.stringify(bad)); });
}
set(attrname, value, ok, bad) {
if (typeof value === "number") {
value = value.toString();
}
jchaos.setAttribute(this.uid, attrname, value, k => {
if (typeof ok === "function") {
ok(k);
} else {
jchaos.print(this.uid + "] set attr " + attrname + " =" + value);
}
}, b => {
if (typeof bad === "function") {
bad(b);
} else {
jchaos.perror(this.uid + "= Error setting attr " + attrname + " =" + value);
}
});
}
async _get() {
var prom = this.syncDS();
return await prom;
}
get(ok, bad) {
this._get().then(ok);
return this.ds;
}
schedule(us, ok, bad) {
jchaos.setSched(this.uid, us, ok, bad);
}
calibrate() {
jchaos.command(this.uid, { "act_name": "calibrateNodeUnit" }, function (data) {
jchaos.print("Calibration done");
}, function (data) {
jchaos.error("Error calibrating:" + JSON.stringify(data));
});
}
setDrvProp(props, ok) {
var msg = {
"act_msg": props,
"act_name": "cu_prop_drv_set"
};
jchaos.command(this.cu, msg, function (data) {
if (typeof ok === "function") {
ok(data);
} else {
jchaos.print("Props set:" + JSON.stringify(props));
}
}, (bad) => {
jchaos.perror("Error setting driver prop:" + JSON.stringify(bad));
})
}
getDrvProp(ok, bad) {
jchaos.command(this.cu, { "act_name": "cu_prop_drv_get" }, function (dd) {
this['drv_prop'] = dd;
if (typeof ok === "function") {
ok(dd);
}
}, bad);
}
setCUProp(props, ok) {
var msg = {
"act_msg": props,
"act_name": "ndk_set_prop"
};
jchaos.command(this.cu, msg, function (data) {
jchaos.print("Props set:" + JSON.stringify(props));
if (typeof ok === "function") {
ok(data);
}
}, (bad) => {
jchaos.perror("Error setting CU prop:" + JSON.stringify(bad));
})
}
getCUProp(ok, bad) {
jchaos.command(tmpObj.node_multi_selected, { "act_name": "ndk_get_prop" }, function (dd) {
this['cu_prop'] = dd;
if (typeof ok === "function") {
ok(dd);
}
}, bad);
}
/**
* return the parent of the node (i.e. US or agent)
*/
parent() {
if (this.desc.hasOwnProperty("ndk_parent")) {
return this.desc.ndk_parent;
} else if (this.desc.hasOwnProperty("instance_description") && this.desc.instance_description.hasOwnProperty("ndk_parent")) {
return this.desc.instance_description.ndk_parent;
}
return "";
}
/**
* return the implementation name
*/
impl() {
if (this.desc.hasOwnProperty("instance_description") && this.desc.instance_description.hasOwnProperty("control_unit_implementation")) {
var impl = this.desc.instance_description.control_unit_implementation
var regex = /\w+$/;
impl = regex.exec(impl);
return impl[0];
}
return "";
}
liveEnable(val, ok, bad) {
if (val) {
this.storage |= 2; // live
} else {
this.storage &= (~2); // live
}
jchaos.setProperty(this.uid, [{ "dsndk_storage_type": this.storage }], ok, bad);
}
logEnable(val, ok, bad) {
if (val) {
this.storage |= 16; // log
} else {
this.storage &= (~16);
}
jchaos.setProperty(this.uid, [{ "dsndk_storage_type": this.storage }], ok, bad);
}
histoEnable(val, ok, bad) {
if (val) {
this.storage |= 1; // histo
} else {
this.storage &= (~1);
}
jchaos.setProperty(this.uid, [{ "dsndk_storage_type": this.storage }], ok, bad);
}
/**
* Send a command to the node
* @param {string} name command name
* @param {object} param comman parameters (if any)
* @param {okcb} ok handler on success
* @param {badcb} bad handler on failure
*/
cmd(name, param, ok, bad) {
jchaos.sendCUCmd(this.uid, name, param, ok, bad);
}
/**
* Start tagging for a given time
* @param {string} tagname tag name
* @param {intefer} ms
* @param {okcb} ok
* @param {badcb} bad
*/
tagForMS(tagname, ms, ok, bad) {
jchaos.tag(tagname, this.uid, 2, ms, ok, bad);
}
/**
* Start tagging for a given number of cycles
* @param {string} tagname tag name
* @param {intefer} ms
* @param {okcb} ok
* @param {badcb} bad
*/
tagForCycle(tagname, cycles, ok, bad) {
jchaos.tag(tagname, this.uid, 1, cycles, ok, bad);
}
init(ok, bad) {
jchaos.node(this.uid, "init", "cu", ok, bad);
}
start(ok, bad) {
jchaos.node(this.uid, "start", "cu", ok, bad);
}
stop(ok, bad) {
jchaos.node(this.uid, "stop", "cu", ok, bad);
}
deinit(ok, bad) {
jchaos.node(this.uid, "deinit", "cu", ok, bad);
}
load(ok, bad) {
jchaos.loadUnload(this.uid, true, ok, bad);
}
unload(ok, bad) {
jchaos.loadUnload(this.uid, false, ok, bad);
}
help() {
var methods = Object.getOwnPropertyNames(this.__proto__);
this['methods'] = methods;
// var methods = Object.keys(obj).filter((key) => typeof obj[key] === 'function');
return JSON.stringify(this.methods);
}
};
/**
* Create a basic instance of the node, with set/get init/deinit/unload/load
* it tries to load the specific interface if found
* @param {string} uid of node
*/
jchaos.chaosNodeCreate = function (uid, ok, bad) {
//createNode(uid).then(ok=>{console.log("HERE");
var obj = new ChaosNode(uid, ok, bad);
var methods = Object.getOwnPropertyNames(obj.__proto__);
obj['methods'] = methods;
return obj;
}
async function createNode(uid) {
const prom = new Promise((resolve, reject) => {
jchaos.node(uid, "desc", "all", (data) => {
if (data.hasOwnProperty("instance_description") && data.instance_description.hasOwnProperty("control_unit_implementation")) {
var impl = data.instance_description.control_unit_implementation;
var regex = /\w+$/;
impl = regex.exec(impl);
var promise =
import('./interface/' + impl + ".js");
promise.then(obj => {
console.log("Adding interface " + impl);
resolve(new obj.default(uid));
}).catch(bad => {
console.log("Adding base interface, because:" + JSON.stringify(bad));
resolve(new ChaosNode(uid));
});
} else {
resolve(new ChaosNode(uid));
}
}, (bad) => { reject(bad); })
});
const obj = await prom;
return obj;
}
/**
* Set Library options options
* @param {object} opt
* @function setOption
*/
jchaos.setOptions = function (opt) {
for (var attrname in opt) {
jchaos.options[attrname] = opt[attrname];
}
}
jchaos.filterAlarmObject = function (dev_alarm, includeall) {
var obj = {}
var all = true;
if (includeall !== undefined) {
all = includeall;
}
for (var key in dev_alarm) {
var value = dev_alarm[key];
if (!jchaos.isReservedKey(key)) {
if ((typeof value === "string") || (typeof value === "number" && ((value > 0) || all))) {
obj[key] = value;
}
}
}
return obj;
}
/**
* Prints a String on the configured console
* @param {string} str
*/
jchaos.print = function (str) {
jchaos.options['console_log'](str);
}
/**
* Prints a String on the configured console error
* @param {string} str
*/
jchaos.perror = function (str) {
jchaos.options['console_err'](str);
}
jchaos.exit = function (str) {
alert(str)
}
/******* REMOTE PROCESS MANAGEMENT ****/
/**
* Helper function to post commands on the process remote management
* @param {string} server rest process remote management server
* @param {string} func REST function
* @param {object} param REST function parameters
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @function basicRmt
*/
jchaos.basicRmt = function (server, func, param, handler, badhandler) {
if (typeof param === "object") {
param['server'] = server;
} else {
param = {};
param['server'] = server;
}
param["api"] = "api/v1/restconsole/" + func;
//return jchaos.basicPost("/api/v1/restconsole/" + func, JSON.stringify(param), handler,badhandler,server);
return jchaos.basicPost("proxy", param, handler, badhandler);
}
/**
* Retrive a given environemnt variable
* @param {string} server rest p
* rocess remote management server
* @param {string} varname environment variable name
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @returns the value on the specified handler.
* @function rmtGetEnvironment
*/
jchaos.rmtGetEnvironment = function (server, varname, handler, badhandler) {
var param = {};
param['variable'] = varname;
return jchaos.basicRmt(server, "getenv", param, handler, badhandler);
}
/**
* Set the specified propery
* @param {string} server rest process remote management server
* @param { {uid:String, propname:String} } prop property name
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @returns the value on the specified handler.
* @function rmtSetProp
*/
jchaos.rmtSetProp = function (server, prop, handler, badhandler) {
return jchaos.basicRmt(server, "setprop", prop, handler, badhandler);
}
/**
*
*/
/**
* Launch a process the specified process on the given remote server
* return a process structure
* @param {string} server rest process remote management server
* @param {string} name program name
* @param {string} cmdline command line
* @param {string} ptype type ("exec": binary, "C++": C++ script")
* @param {string} workdir remote local directory
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @returns {object} return a process object with many status and information
* @function rmtCreateProcess
*/
jchaos.rmtCreateProcess = function (server, name, cmdline, ptype, workdir, handler, badhandler) {
var param = {};
param['cmdline'] = cmdline;
param['ptype'] = ptype;
param['pname'] = name;
if (workdir != null && workdir != "") {
param['workdir'] = workdir;
}
console.log("create process:" + JSON.stringify(param));
return jchaos.basicRmt(server, "create", param, handler, badhandler);
}
/**
* Retrive a process working directory
* return a zip file
*/
/**
* Return a zip file contaning the working directory of the specified process
* can be used to retrieve outputs of remote runs
* @param {string} server rest process remote management server
* @param {string} uid the process uid returned by the rmtCreateProcess
* @param {string} workdir working dir to retrieve and zip
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @function rmtCreateProcess
*/
jchaos.rmtDownload = function (server, uid, workdir, handler, badhandler) {
var param = {};
param['uid'] = uid;
if (workdir != null && workdir != "") {
param['workdir'] = workdir;
}
console.log("Download process outputs:" + JSON.stringify(param));
return jchaos.basicRmt(server, "download", param, handler, badhandler);
}
/**
*/
/**
* Upload a script/executable on the remote server
* return the path
* @param {string} server rest process remote management server
* @param {string} name program name
* @param {string} ptype type ("exec": binary, "C++": C++ script")
* @param {string} content base64 encoded content to upload
* @returns {object} return the path of the remote process
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @function rmtUploadScript
*/
jchaos.rmtUploadScript = function (server, name, ptype, content, handler, badhandler) {
if ((name instanceof Object) && (ptype instanceof Function) && (content instanceof Function)) {
return jchaos.basicRmt(server, "load", name, ptype, content);
}
var param = {};
param['script_name'] = name;
param['eudk_script_language'] = ptype;
param['eudk_script_content'] = btoa(unescape(encodeURIComponent(content)));
return jchaos.basicRmt(server, "load", param, handler, badhandler);
}
/**
* Return a list of process on the given server
* @param {string} server rest process remote management server
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @returns {object[]} return a list of process descriptors
* @function rmtListProcess
*/
jchaos.rmtListProcess = function (server, handler, badhandler) {
var param = {};
console.log("List process on: " + server);
return jchaos.basicRmt(server, "list", param, handler, badhandler);
}
/**
* Write on the remote console of the specified process
* @param {string} server rest process remote management server
* @param {string} uid the process uid returned by the rmtCreateProcess
* @param {string} str line to send
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @dfunction rmtSetConsole
*/
jchaos.rmtSetConsole = function (server, uid, str, handler, badhandler) {
var param = {};
param['uid'] = uid;
param['data'] = btoa(unescape(encodeURIComponent(str + "\n")));
return jchaos.basicRmt(server, "setconsole", param, handler, badhandler);
}
/**
* Reads the console of the specified process uid
* @param {string} server rest process remote management server
* @param {string} uid the process uid returned by the rmtCreateProcess
* @param {integer} fromline get from this line
* @param {integer} toline until this line (-1 means end)
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @dfunction rmtGetConsole
*/
jchaos.rmtGetConsole = function (server, uid, fromline, toline, handler, badhandler) {
var param = {};
param['uid'] = uid;
param['fromline'] = fromline;
param['toline'] = toline;
return jchaos.basicRmt(server, "getconsole", param, handler, badhandler);
}
/**
* Kill the specified process
* @param {string} server rest process remote management server
* @param {string} uid the process uid returned by the rmtCreateProcess
* @param {okcb} handler handler on success
* @param {badcb} badhandler handler on failure
* @function rmtKill
*/
jchaos.rmtKill = function (server, uid, handler, badhandler) {
var param = {};
param['uid'] = uid;
return jchaos.basicRmt(server, "kill", param, handler, badhandler);
}
/**
* Purge a list of process to a given level (0 soft (EXCEPTION), 1 medium (ENDED and EXCEPTION), 2 hard (ALL)
* @param {string} server rest process remote management server
* @param {integer} level purge level
* @param {okcb} [handler] handler on success
* @param {badcb} [badhandler] handler on failure
* @function rmtPurge
*/
jchaos.rmtPurge = function (server, level, handler, badhandler) {
var param = {};
param['level'] = level;
return jchaos.basicRmt(server, "purge", param, handler, badhandler);
}
/******************************/
/****** WIDGET */
/**
* @hide
*/
jchaos.progressBar = function (msg, id, lab) {
var progressbar;
var instant = $('<div></div>').html('<div id="' + id + '"><div class="progress-label">' + lab + '</div></div>').dialog({
title: msg,
position: "top",
open: function () {
progressbar = $("#" + id)
var progressLabel = $(".progress-label");
progressbar.progressbar({
value: false,
change: function () {
var val = progressbar.progressbar("value");
progressLabel.text(val + "%");
},
complete: function () {
$(this).parent().dialog("close");
}
});
},
close: function () {
$(this).remove();
}
});
}
/***** */
/**
* Helper function that is the base of all commands to the !CHAOS REST SERVER
* the server is specified in the option
* @param {string} func REST function to perform
* @param {string} params parameters
* @param {okcb} [handler] handler on success, if present the call will be asynchronous
* @param {badcb} [badhandler] handler on failure
* @param {string} [server] override the default server
* @function basicPost
*/
jchaos.basicPost = function (func, oparam, handleFunc, handleFuncErr, server, logop) {
var request;
var now = (new Date()).getTime();
var params = oparam;
request = new XMLHttpRequest();
var srv = jchaos.options.uri;
XMLHttpRequest.responseType = "json";
if (typeof server === "string") {
srv = server;
}
var url = srv + "/" + func;
var could_make_async = (typeof handleFunc === "function");
jchaos['nops']++;
request['jchaos_ts'] = now;
request['jchaos_uid'] = jchaos['nops'];
request['jchaos_url'] = url;
if (typeof oparam === "object") {
if (oparam.hasOwnProperty("devs") && (oparam.devs instanceof Array)) {
if (oparam.devs.length == 0) {
return;
}
}
request['jchaos_param'] = oparam;
} else {
alert("NO JSON POST")
request['jchaos_param'] = params;
}
if (could_make_async == false) {
request.open("POST", url, false);
request.send(JSON.stringify(params));
if (request.status == 200) {
try {
var json = JSON.parse(request.responseText);
jchaos.logops(request, logop);
return json;
} catch (err) {
var str = "jchaos.basicPost Error parsing json '" + err + "' body returned:'" + request.responseText + "' post:'" + params + "'";
jchaos.perror(str);
request['jchaos_error'] = str;
jchaos.logops(request, logop);
return null;
}
}
jchaos.perror("bad status:" + request.status + " error:" + request.responseText);
return null;
}
request.open("POST", url, (jchaos.ops_on_going > jchaos.options.limit_on_going) ? false : (jchaos.options.async));
request.timeout = jchaos.options.timeout;
jchaos.ops_on_going++;
request.onreadystatechange = function (e) {
request['jchaos_answer_ts'] = (new Date()).getTime();
if (request.readyState == 4) {
jchaos.ops_on_going--;
if (request.status == 200) {
var json;
try {
json = JSON.parse(request.responseText);
jchaos.logops(request, logop);
} catch (err) {
var str = "jchaos.basicPost Error parsing json '" + err + "' body returned:'" + request.responseText + "'" + "' post:'" + params + "'";;
request['jchaos_error'] = str;
jchaos.logops(request, logop);
if ((typeof handleFuncErr === "function")) {
return handleFuncErr(str, request);
} else {
jchaos.perror(str);
return str;
}
}
if (could_make_async) {
var lat = (new Date()).getTime() - now;
jchaos['latency'] = lat;
jchaos['latency_tot'] += lat;
jchaos['numok'] = jchaos['numok'] + 1;
if(jchaos['numok']%10==0){
jchaos['latency_avg'] = jchaos['latency_tot'] / 10;
jchaos['latency_tot']=0;
}
handleFunc(json, request);
jchaos.options.on_restOk(request);
}
return json;
} else {
var json;
var str;
jchaos['errors']++;
try {
json = JSON.parse(request.responseText);
str = "Error '" + request.status + "' API '" + params + "' returned:'" + request.responseText + "'";
} catch (pr) {
json = request.responseText;
str = "jchaos.basicPost Error parsing json body returned:'" + request.responseText + "'" + "' post:'" + params + "'";;
}
var str = "POST " + url + " body:\"" + params + "\" went wrong, result:" + request.status + " state:" + request.readyState;
// jchaos.perror(str);
request['jchaos_error'] = str;
jchaos.logops(request, logop);
if ((typeof handleFuncErr === "function")) {
handleFuncErr(json, request);
} else {
if ((typeof json === "object")) {
if (json.hasOwnProperty('error_status')) {
jchaos.perror("Error:" + json.error_status);
}
}
}
}
}
}
request.onerror = function (e) {
jchaos.perror("request error:" + request.statusText);
//throw