diff --git a/js/top/jamapp.js b/js/top/jamapp.js new file mode 100644 index 0000000..55de449 --- /dev/null +++ b/js/top/jamapp.js @@ -0,0 +1,1907 @@ +/** + ** ============================== + ** O O O OOOO + ** O O O O O O + ** O O O O O O + ** OOOO OOOO O OOO OOOO + ** O O O O O O O + ** O O O O O O O + ** OOOO OOOO O O OOOO + ** ============================== + ** Dr. Stefan Bosse http://www.bsslab.de + ** + ** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED + ** BY THE AUTHOR(S). + ** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED, + ** MODIFIED, OR OTHERWISE USED IN A CONTEXT + ** OUTSIDE OF THE SOFTWARE SYSTEM. + ** + ** $AUTHORS: Stefan Bosse + ** $INITIAL: (C) 2006-2018 bLAB + ** $CREATED: 13-12-16 by sbosse. + ** $VERSION: 1.6.15 + ** + ** $INFO: + ** + ** JAM APP using jamlib and terminal UI + ** + ** Command line options: + ** + ** style:invert|black|simple + ** mode:server connect:true + ** config: + ** + ** $ENDOFINFO + */ +global.config={simulation:false}; + +var options = { + version:'1.6.15' +} + +var Io = Require('com/io'); +var Comp = Require('com/compat'); +var JamLib = Require('top/jamlib'); +var Name = Require('com/pwgen'); +var Aios = JamLib.Aios; +var Net = Require('dos/network'); +var Buf = Require('dos/buf'); +var Obj = Comp.obj; +var Args = Comp.args; +var Status = Net.Status; +var Command = Net.Command; +var Getenv = Require('com/getenv'); +var satelize = Require('dos/ext/satelize'); +var UI = Require('ui/app/app'); +var util = Require('util'); +var Proc = Require('child_process'); + +var nameopts = {length:8, memorable:true, lowercase:true}, + Nameopts = {length:8, memorable:true, uppercase:true}; + +var MB = function (bytes) { return int(bytes/1024/1024) } +var styles = { + simple:{ + button:{ + // border:{type:'line',bg:'white'}, + border:{type:'none'}, + black: 'blue', + }, + info:{ + bg:'black', + fg:'yellow', + border:{type:'none'}, + label:{fg:'green',bold:true}, + }, + input:{ + bg:'lightgrey', + text:{fg:'black'}, + border:{type:'none'}, + label:{fg:'green',bold:true}, + }, + label: { + bold:true, + fg:'green', + }, + list: { + bg:'black', + border:{type:'none'}, + label:{fg:'green',bold:true}, + }, + log:{ + bg:'black', + border:{type:'none'}, + label:{fg:'green',bold:true}, + }, + tree: { + bg:'black', + border:{type:'none'}, + label:{fg:'green',bold:true}, + }, + keyboard:{ + bg:'yellow', + border:{type:'ch',ch:' ',bg:'yellow'}, + label:{bg:'yellow',fg:'black'} + }, + filemanager:{ + bg:'yellow', + fg:'black', + arrows: { + fg:'red', + bg:'white', + }, + border:{type:'ch',ch:' ',bg:'yellow'}, + box:{ + bg:'white' + }, + label:{fg:'white',bg:'yellow'}, + input:{ + bg:'white', + fg:'black', + }, + }, + }, + + black:{ + button:{ + border:{type:'line',fg:'white'}, + black: 'blue', + }, + info:{ + fg:'yellow', + border:{type:'line',fg:'green'}, + label:{fg:'green',bold:true}, + }, + input:{ + fg:'yellow', + border:{type:'line',fg:'green'}, + label:{fg:'green',bold:true}, + }, + label: { + bold:true, + fg:'green', + }, + list: { + border:{type:'line',fg:'green'}, + label:{fg:'green',bold:true}, + }, + tree: { + border:{type:'line',fg:'green'}, + label:{fg:'green',bold:true}, + }, + keyboard:{ + border:{type:'line'} + }, + filemanager:{ + border:{type:'line',fg:'green'}, + arrows: { + fg:'red', + bg:'default', + }, + box:{ + bg:'default', + fg:'white', + border:{bg:'default',type:'line',fg:'green'} + }, + input:{ + border:{type:'line'} + }, + label:{ + fg:'white', + } + }, + }, + default: { + button: { + black:'black' + }, + filemanager:{ + border:{type:'line'}, + arrows: { + fg:'red', + bg:'default', + }, + box:{ + bg:'default', + border:{bg:'default',type:'line'} + }, + input:{ + border:{type:'line'} + }, + label:{ + fg:'blue', + } + }, + keyboard:{ + border:{type:'line'} + }, + label:{fg:'black',bold:true}, + } +} +// Create top-level App with UI +var appTerm = function (_options) { + var self=this, + id=Name.generate(nameopts), + log,log2, + changed=false, + p; + this.config = { + agents: {level:1}, + autoconnect:false, + domain: 'default', + expert:false, + keyboard:false, // sync with this.UI.options.keyboard + public:{'IP(1)':{address:'ag-0.de',port:10001,local:'*',enable:true}}, + nodename:id, // pre-guess + links:['IP(1)','IP(2)','IP(3)','IP(4)','NORTH','SOUTH','WEST','EAST'], + log:{node:false,agent:false,class:false,time:false}, + logJam:{world:false,node:false,pid:false,time:false}, + mode:'gui', + proto:'udp', + script:'//Type Here\n', + security:false, + sensors:false, + simple:false, + verbose:0, // sync with this.options.verbose + worldname:id.toUpperCase() + }; + this.options = { + configFile:JamLib.environment.config||'jam.app.config', + env:{}, + geo:undefined, + hostname:Io.hostname(), + myip:'localhost', + monitor:0, + onexit:false, + start:false, + print:console.log, + verbose:0, + }; + for(p in _options) this.options[p]=_options[p]; + + + this.err=function (msg,err) {console.log('[APP] Error: '+msg); throw (err||'[JAM] Error')} + this.warn=function (msg) {console.log('[APP] Warning: '+msg);} + this.out=this.log=function (msg) {console.log('[APP] '+msg);} + + if (!this.options.terminal) this.options.terminal=(process.platform === 'win32' ? 'windows-ansi' : 'xterm-color'); + if (process.platform === 'android') this.config.keyboard=true; + + this.readConfig(); + + if (JamLib.environment.mode=='server') this.config.mode='server'; + if (this.config.mode=='server' && JamLib.environment.connect=='true') this.config.autoconnect=true; + + if (!this.config.nodename) this.out('Setting node name to '+id),this.config.nodename=id,changed=true; + if (!this.config.worldname) this.config.worldname=id.toUpperCase(),changed=true; + + // AIOS extensions we provide + this.extensions = { + config: { + levels:[3], + fun: function () { return self.config }, + args: 0 + }, + connect: { + levels:[3], + fun: function (to) { self.jam.world.connectTo(to); }, + args:1 + } + } + + // Sensor TS provider + this.provider = function (pat) { + if (process.sensor) switch (pat.length) { + case 2: + switch (pat[0]) { + case 'SENSORS': + return [pat[0],process.sensor.info()]; + } + break; + case 3: + switch (pat[0]) { + case 'SENSOR': + process.sensor.start(pat[1]); + return [pat[0],pat[1],process.sensor.read(pat[1])]; + } + break; + } + } + + this.events=[]; + this.todo=[]; + this.exit = []; + this.status = {initialized:false,run:false,connected:false,connecting:false,error:false}; + this.links = {}; + this.config.links.forEach(function (dir) { + self.links[dir]=self.config.public[dir]||{}; + }); + + this.classes={}; + + if (this.config.mode!='server') log = function (msg) { self.logWin.log(msg) }; + else log = console.log; + + Aios.config({print:log}); + this.err=function (msg,err) {log('[APP] Error: '+msg); throw (err||'[JAM] Error')} + this.warn=function (msg) {log('[APP] Warning: '+msg);} + this.out=this.log=function (msg) {log('[APP] '+msg);} + + if (this.config.mode!='server') log2 = function (msg) { self.msgWin.log(msg) }; + else log2 = console.log; + + Aios.config({printAgent:log2}); + this.log2 = log2; + + this.jam = undefined; + if (this.config.mode!='server') { + if (this.config.simple || process.argv.indexOf('style:simple')!=-1) + this.styles=styles.simple; + else if (process.platform=='android' || + process.platform=='win32' || + process.argv.indexOf('style:invert')!=-1 || + process.argv.indexOf('style:black')!=-1) + this.styles=styles.black; + else this.styles=styles.default; + } else { + this.dialog=console.log; + } + + if (changed) this.saveConfig(); +}; + +appTerm.prototype.connect = function () { + var self=this,p,to; + if (!this.jam || !this.jam.world || this.status.connecting) return; + this.status.connecting=true; + setTimeout(function () { self.status.connecting=false; self.update('status') }, 5000); + for(p in this.links) { + if (!this.links[p].enable) continue; + if (p.indexOf('IP')==0 && this.links[p].address && this.links[p].port) { + to=Aios.Chan.addr2url(this.links[p]); + this.jam.world.connectTo(Aios.DIR.IP(to)); + } + } + +} + +appTerm.prototype.createAgent = function (cls,args,level,confirm) { + var msg; + try { + if (!args) throw 'Invalid arguments'; + if (level == undefined) level=1; + msg=cls+'('+util.inspect(args)+') Level '+level; + id=this.jam.createAgent(cls,args,level); + if (id==null) throw ('Agent creation failed: '+this.jam.error); + msg += (' : '+id); + this.log('Created agent '+msg); + if (confirm) this.dialog('Created agent '+msg); + } catch (e) { + this.dialog(msg+' Error: '+e); + } +} + +appTerm.prototype.emit=function (event,args) { + var e; + for (e in this.events) { + var ev=this.events[e]; + if (ev[0]==event) ev[1](args); + } +} + +appTerm.prototype.init = function () { + if (this.config.mode!='server') this.setupGui(); +} + +// INITILIAZE JAM +appTerm.prototype.initJAM = function () { + var self=this,options={},connected={},p,status; + this.out('Creating JAM ..'); + options.log=this.config.log; + options.logJam=this.config.logJam; + options.verbose=this.options.verbose||1; + options.id=this.config.nodename; + options.world=this.config.worldname; + options.provider=this.provider; + + // construct connections + // TODO: multiple IP(*) ports! + options.connections={}; + for(p in this.links) { + if (!this.links[p].enable) continue; + if (p.indexOf('IP')==0 && !options.connections.ip) options.connections.ip={ + from:this.links[p].local?this.links[p].local:'*', + // to:this.links[p].address?Aios.Chan.addr2url(this.links[p]):undefined, + on: { + 'link+': function (url) { + connected[url]=true; + self.status.connecting=false; self.status.connected=true; + self.update('status') + }, + 'link-': function (url) { + var p,c=0; + connected[url]=false; + for(p in connected) if (connected[p]) c++; + if (c==0) { + self.status.connecting=false; self.status.connected=false; + self.update('status') + } + } + }, + proto:'udp', + multicast:true + } + } + // this.out(util.inspect(options)) + this.jam=JamLib.Jam(options); + this.jam.init(); + for(var p in this.extensions) { + this.jam.extend(this.extensions[p].levels,p,this.extensions[p].fun,this.extensions[p].args); + } + this.status.initialized=true; + for(p in this.classes) { + status=this.jam.readClass(this.classes[p],{verbose:1}); + if (!status) {this.status.error='Load failed';delete this.classes[p]}; + this.update('status'); + } +} + +appTerm.prototype.io = function () { + +} + +appTerm.prototype.loadClassFile = function (file) { + var status,self=this, + mod=Comp.filename.removeext(Comp.filename.basename(file)); + if (mod=='') mod=Comp.filename.basename(file); + this.classes[mod]=file; + if (this.status.initialized) { + try { + status=this.jam.readClass(file, + { + verbose:1, + error:function (e) {throw e} + }); + } catch (e) {self.log(e); status=false}; + if (!status) this.status.error='Load failed',delete this.classes[mod]; else this.status.error=false; + this.update('status'); + if (!status) this.dialog(this.jam.error); + } + if (this.config.mode!='server' && this.UI.pages[this.CS.pages.classes] && + this.UI.pages[this.CS.pages.classes].tree1) + this.UI.pages[this.CS.pages.classes].tree1.set(this.classes); +} + + + +appTerm.prototype.on=function (event,callback) { + this.events.push([event,callback]); +} + +// PRINT: Smart print function // obsolete // +appTerm.prototype.print = function (msg,header,depth,logger) { + var self = this; + var lines=[], + line=''; + if (depth==_) depth=1; + function isvec(obj) {return(Comp.obj.isArray(obj) && (obj.length == 0 || !Comp.obj.isArray(obj[0])))} + function ismat(obj) {return(Comp.obj.isArray(obj) && obj.length > 0 && Comp.obj.isArray(obj[0]))} + function mat(o,depth) { + // matrix + var lines=[]; + var line = ''; + if (header) {line=header; header=_}; + for (var j in o) { + var row=o[j]; + line += Comp.printf.list(row,function (v) { + return (Comp.obj.isArray(v)?(depth>0?'['+vec(v,depth-1)+']':'[..]'): + Comp.obj.isObj(v)?(depth>0?obj(v,depth-1):'{..}'):v); + }); + lines.push(line); + line=''; + } + return lines; + } + function vec(v,depth) { + // vector + var lines=[]; + var line = ''; + if (header) {line=header; header=_}; + if (v.length==0) return(line+'[]'); + else { + // can still contain matrix elements that must be separated + var sep='',sepi=''; + for (var p in v) { + if (ismat(v[p])) { + //self.log.log(line); line=' '; + if (depth>0) { + lines = mat(v[p],depth-1); + line += sep+'['; sepi=''; + Comp.array.iter(lines,function (line2) { + line += sepi+'['+line2+']'; + sepi=','; + }); + line += ']'; + sep=','; + } else { + line += sep+'[[..]]'; + sep=','; + } + } + else if (isvec(v[p])) { + //self.log.log(line); line=' '; + line += sep+vec(v[p],depth-1); + sep=','; + } + else { + line += sep+(Comp.obj.isArray(v[p])?(depth>0?vec(v[p],depth-1):'[..]'): + Comp.obj.isObj(v[p])?(depth>0?obj(v[p],depth-1):'{..}'):v[p]); + sep=','; + } + } + if (line!='') return line; + } + } + function obj(o,depth) { + var line=''; + var sep=''; + if (header) {line=header; header=_}; + line += '{'; + for (var p in o) { + if (!Comp.obj.isFunction(o[p])) { + line += sep + p+':'+ + (Comp.obj.isArray(o[p])?(depth>0?vec(o[p],depth-1):'[..]'): + Comp.obj.isObj(o[p])?(depth>0?obj(o[p],depth-1):'{..}'):o[p]); + sep=','; + } else { + line += sep + p+':'+'function()'; + sep=','; + } + } + return line+'}'; + } + + function str(s) { + var line=''; + var lines=[]; + var lines2 = Comp.string.split('\n',msg); + if (header) {line=header; header=_}; + if (lines2.length==1) + lines.push(line+msg); + else { + Comp.array.iter(lines2,function (line2,i) { + if (i==0) lines.push(line+line2); + else lines.push(line2); + }); + } + return lines; + } + + if (ismat(msg)) lines = Comp.array.concat(lines, + Comp.array.map(mat(msg,depth-1),function (line){ + return ' '+line})); + else if (Comp.obj.isString(msg)) lines = Comp.array.concat(lines,str(msg)); + else if (isvec(msg)) lines.push(vec(msg,depth-1)); + else if (Comp.obj.isObj(msg)) lines.push(obj(msg,depth-1)); + else { + if (header) {line=header; header=_}; + line += msg; + lines.push(line); + } + + if (logger==undefined) return lines; else + Comp.array.iter(lines,function (line) {logger(line)}); +} + +/** quit app + * + */ +appTerm.prototype.quit = function (stat) { + this.saveConfig(); + return process.exit(stat); +} + +/** Read configuation file + * + */ +appTerm.prototype.readConfig = function (file) { + // TODO + var text,config; + if (!file) file=this.options.configFile; + this.out('Reading config file '+file); + text=Io.read_file(file); + if (text) { + try { config=JSON.parse(text); for(var p in config) this.config[p]=config[p] } + catch (e) {this.err('Parsing config file failed: '+e)}; + } +} + +/** Save configuation file + * + */ +appTerm.prototype.saveConfig = function (file) { + // TODO + var text=JSON.stringify(this.config,null,2); + if (!file) file=this.options.configFile; + this.out('Saving config file '+file); + Io.write_file(file,text); +} + +appTerm.prototype.setupGui = function () { + var self=this, + page, + p,i,x,y,first; + // Information bar visible on all pages + this.UI = UI.UI({ + pages:20, + styles:this.styles, + terminal:this.options.terminal, + title:'JAMAPP (C) Stefan Bosse' + }); + this.UI.init(); + this.UI.options.keyboard=this.config.keyboard; + + // Layout configuration + this.CF = { + fm: { + height:this.UI.layout.small?this.UI.screen.height-4:Math.min(25,this.UI.screen.height-4), + top:2, + width:this.UI.layout.small?this.UI.screen.width:'60%', + }, + info:{ + top:this.UI.layout.small?this.UI.screen.height-4:this.UI.screen.height-3, + height:this.UI.layout.small?4:3 + }, + menu: { + buttons:{ + top:4 + } + }, + setup: { + checkboxes:{ + x0:this.UI.layout.small?4:4, + x1:this.UI.layout.small?20:int(this.UI.screen.width/2), + y0:this.UI.layout.small?16:12, + y1:this.UI.layout.small?24:20, + left2:this.UI.layout.small?4:30, + left3:this.UI.layout.small?4:4, + top3:this.UI.layout.small?5:4, + left4:this.UI.layout.small?4:50, + top4:this.UI.layout.small?15:12, + }, + labels:{ + input:{ + top:this.UI.layout.small?9:5, + center:this.UI.layout.small?undefined:true, + left:this.UI.layout.small?'65%':undefined, + }, + top1:{ + content:this.UI.layout.small?'Setup':'Setup [Links]', + }, + top2:{ + content:this.UI.layout.small?'Setup':'Setup [JAM]', + }, + top23:{ + content:this.UI.layout.small?'Setup':undefined, + }, + top3:{ + content:this.UI.layout.small?'Script':'Setup [Script]', + }, + top4:this.UI.layout.small?13:10 + }, + inputs:{ + remoteip:{ + top:4, + left:4, + right:undefined, + width:this.UI.layout.small?'80%':int(this.UI.screen.width/2)-10 + }, + remoteipp:{ + top:this.UI.layout.small?8:4, + left:this.UI.layout.small?4:undefined, + right:this.UI.layout.small?undefined:4, + width:this.UI.layout.small?'50%':int(this.UI.screen.width/2)-10 + }, + localip:{ + top:this.UI.layout.small?12:8, + left:this.UI.layout.small?4:undefined, + right:this.UI.layout.small?undefined:4, + width:this.UI.layout.small?'50%':int(this.UI.screen.width/2)-10 + }, + protect:{ + top:this.UI.layout.small?16:8, + left:4, + right:undefined, + width:this.UI.layout.small?'50%':int(this.UI.screen.width/2)-10 + }, + script:{ + top:4, + left:2, + height:this.UI.screen.height-8, + width:this.UI.screen.width-4 + } + }, + }, + control:{ + center:this.UI.layout.small?undefined:true, + left:this.UI.layout.small?1:undefined, + left2:this.UI.layout.small?1:'10%', + right2:this.UI.layout.small?1:'10%', + width:this.UI.layout.small?this.UI.screen.width-2:'80%', + width2:this.UI.layout.small?12:'30%', + info1:{ + height:this.UI.layout.small?4:3, + } + }, + classes:{ + center:this.UI.layout.small?undefined:true, + left:this.UI.layout.small?1:undefined, + left2:this.UI.layout.small?1:'10%', + right2:this.UI.layout.small?1:'10%', + width:this.UI.layout.small?this.UI.screen.width-2:'80%', + width2:this.UI.layout.small?this.UI.screen.width/2-2:'40%', + labels:{ + center:this.UI.layout.small?undefined:true, + right:this.UI.layout.small?4:undefined, + top:this.UI.layout.small?'Classes':'Agent Classes', + } + }, + stats:{ + left:this.UI.layout.small?1:4, + width:this.UI.layout.small?this.UI.screen.width-4:self.UI.screen.width-8, + labels:{ + center:true, + right:undefined, + top:this.UI.layout.small?'Info':'System Info', + } + }, + explorer:{ + left:this.UI.layout.small?1:4, + right:this.UI.layout.small?1:4, + width:this.UI.layout.small?this.UI.screen.width-4:self.UI.screen.width-8, + labels:{ + center:this.UI.layout.small?undefined:true, + right:this.UI.layout.small?4:undefined, + top:'Explorer', + } + }, + log1:{ + left:this.UI.layout.small?1:4, + width:this.UI.layout.small?this.UI.screen.width-4:undefined + }, + log2:{ + left:this.UI.layout.small?1:4, + width:this.UI.layout.small?this.UI.screen.width-4:undefined + } + } + + + // Layout independent content structure + this.CS = { + agents:{ + buttons:{ + clear:this.UI.button({left:this.CF.log1.left,top:4,content:'Clear',bg:'green'}), + }, + log1:this.UI.log({left:this.CF.log1.left,width:this.CF.log1.width, + top:8,height:this.UI.screen.height-12,label:'Agent Messages', + arrows:{up:'[-]',down:'[+]',width:3,height:1,fg:'red',bg:'default'}}) + }, + dialog: function (msg,callback) { + var lines = int(msg.length/(self.UI.screen.width/2-4))+2; + var dia = self.UI.dialog({ + width:self.UI.layout.small?'80%':'50%', + height:lines+4, + center:true, + okButton : 'Okay' + }); + dia.ask(msg,function () {dia.destroy(); if (callback) callback()}) + }, + info: this.UI.info({ + top:this.CF.info.top, + width:this.UI.screen.width-2, + height:this.CF.info.height, + wrap:true, + label:'Information' + }), + menu: { + buttons:{ + top:4, + quit:this.UI.button({left:1,content:'QUIT'}), + setup:this.UI.button({right:1,content:'SETUP'}), + control:this.UI.button({top:this.CF.menu.buttons.top,center:true,bg:'blue',width:'80%',content:'Control'}), + jam:this.UI.button({top:this.CF.menu.buttons.top+4,center:true,bg:'blue',width:'80%',content:'JAM'}), + agents:this.UI.button({top:this.CF.menu.buttons.top+8,center:true,bg:'blue',width:'80%',content:'Agents'}), + logging:this.UI.button({top:this.CF.menu.buttons.top+12,center:true,bg:'blue',width:'80%',content:'Logging'}), + }, + labels:{ + top:this.UI.label({ + center:true,top:1, + content:'JAMapp'+(this.UI.layout.small?'':(' '+options.version+' (Dr. Stefan Bosse)')) + }), + } + }, + setup: { + buttons:{ + less1:this.UI.button({left:1,content:'<< Less'}), + less2:this.UI.layout.small?this.UI.button({left:1,content:'<< Less'}):undefined, + less3:this.UI.button({left:1,content:'<< Less'}), + menu:this.UI.button({left:1,content:'<< Menu'}), + more1:this.UI.button({right:1,content:'More'}), + more2:this.UI.layout.small?this.UI.button({right:1,content:'More'}):undefined, + more3:this.UI.button({right:1,content:'Script'}), + }, + checkboxes:{ + agentid:this.UI.checkbox({left:4,top:12,text:'Agent ID',value:this.config.log.agent}), + parentid:this.UI.checkbox({left:4,top:14,text:'Parent ID',value:this.config.log.parent}), + agenttime:this.UI.checkbox({left:4,top:16,text:'Time',value:this.config.log.time}), + agentclass:this.UI.checkbox({left:4,top:18,text:'Class',value:this.config.log.class}), + msgpid:this.UI.checkbox({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.checkboxes.top4,text:'PID',value:this.config.logJam.pid}), + msgnode:this.UI.checkbox({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.checkboxes.top4+2,text:'Node',value:this.config.logJam.node}), + msgworld:this.UI.checkbox({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.checkboxes.top4+4,text:'World',value:this.config.logJam.world}), + msgtime:this.UI.checkbox({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.checkboxes.top4+6,text:'Time ',value:this.config.logJam.time}), + verbose:this.UI.checkbox({left:this.CF.setup.checkboxes.left3,top:this.CF.setup.checkboxes.top3,text:'Verbose',value:false}), + softkey:this.UI.checkbox({left:this.CF.setup.checkboxes.left3,top:this.CF.setup.checkboxes.top3+2,text:'Soft Keyboard',value:this.config.keyboard}), + expert:!this.UI.layout.small?this.UI.checkbox({left:this.CF.setup.checkboxes.left3,top:this.CF.setup.checkboxes.top3+4,text:'Expert Mode',value:this.config.expert}):undefined, + security:!this.UI.layout.small?this.UI.checkbox({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.checkboxes.top3+4,text:'Security',value:this.config.security}): + this.UI.checkbox({left:this.CF.setup.checkboxes.left3,top:this.CF.setup.checkboxes.top3+6,text:'Security',value:this.config.security}) + , + sensors:!this.UI.layout.small?this.UI.checkbox({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.checkboxes.top3+2,text:'Sensors',value:this.config.sensors}):undefined, + simple:!this.UI.layout.small?this.UI.checkbox({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.checkboxes.top3,text:'Simple UI',value:this.config.simple}): + this.UI.checkbox({left:this.CF.setup.checkboxes.left3,top:this.CF.setup.checkboxes.top3+4,text:'Simple UI',value:this.config.simple}) + , + http:this.UI.layout.small?this.UI.radiobutton({left:4,top:6,text:'HTTP',value:false,group:2}): + this.UI.radiobutton({left:this.CF.setup.checkboxes.left4,top:12,text:'HTTP',value:false,noshow:config.expert,group:2}), + udp:this.UI.layout.small?this.UI.radiobutton({left:4,top:8,text:'UDP',value:true,group:2}): + this.UI.radiobutton({left:this.CF.setup.checkboxes.left4,top:14,text:'UDP',value:true,noshow:config.expert,group:2}), + autoconnect:this.UI.layout.small?this.UI.checkbox({left:4,top:10,text:'Autoconnect',value:this.config.autoconnect}): + this.UI.checkbox({left:this.CF.setup.checkboxes.left4,top:16,text:'Autoconnect',value:this.config.autoconnect}), + }, + inputs:{ + remoteip:this.UI.input({top:this.CF.setup.inputs.remoteip.top, + left:this.CF.setup.inputs.remoteip.left, + width:this.CF.setup.inputs.remoteip.width, + label:'Remote IP Address',value:this.links[this.config.links[0]].address||''}), + remoteipp:this.UI.input({top:this.CF.setup.inputs.remoteipp.top, + left:this.CF.setup.inputs.remoteipp.left, + right:this.CF.setup.inputs.remoteipp.right, + width:this.CF.setup.inputs.remoteipp.width, + label:'Remote IP Port',value:String(this.links[this.config.links[0]].port||'')}), + localip:this.UI.input({top:this.CF.setup.inputs.localip.top, + left:this.CF.setup.inputs.localip.left, + right:this.CF.setup.inputs.localip.right, + width:this.CF.setup.inputs.localip.width, + label:'Local IP Port', + value: + this.links[this.config.links[0]].local?String(this.links[this.config.links[0]].local):'*'}), + protect:this.UI.input({top:this.CF.setup.inputs.protect.top, + left:this.CF.setup.inputs.protect.left, + right:this.CF.setup.inputs.protect.right, + width:this.CF.setup.inputs.protect.width, + label:'Security Key', + value: + '(00)[0:0:0:0:0:0]'}), + script:this.UI.input({ + top:this.CF.setup.inputs.script.top, + center:this.CF.setup.inputs.script.center, + left:this.CF.setup.inputs.script.left, + width:this.CF.setup.inputs.script.width, + height:this.CF.setup.inputs.script.height, + label:'Start Script', + multiline:true, + scrollable:true, + value:this.config.script, + }), + }, + labels:{ + agentflags:this.UI.label({left:4,top:10,content:'Agent Message Flags'}), + input:this.UI.label({center:this.CF.setup.labels.input.center, + left:this.CF.setup.labels.input.left, + right:this.CF.setup.labels.input.right, + top:this.CF.setup.labels.input.top, + content:'IP(1)',mutable:true}), + messageflags:this.UI.label({left:this.CF.setup.checkboxes.left2,top:this.CF.setup.labels.top4,content:'JAM Message Flags'}), + protocol:this.UI.layout.small?this.UI.label({left:4,top:4,content:'Link Protocol (IP)'}): + this.UI.label({left:this.CF.setup.checkboxes.left4,top:10, + content:'Link Protocol (IP)', + noshow:options.expert}), + top1:this.UI.label({center:true,top:1,content:this.CF.setup.labels.top1.content}), + top2:this.UI.layout.large?undefined:this.UI.label({center:true,top:1,content:this.CF.setup.labels.top2.content}), + top23:this.UI.layout.small?this.UI.label({center:true,top:1,content:this.CF.setup.labels.top23.content}):undefined, + top3:this.UI.layout.small?this.UI.label({right:1,top:1,content:this.CF.setup.labels.top3.content}):this.UI.label({center:true,top:1,content:this.CF.setup.labels.top3.content}), + }, + }, + control:{ + buttons:{ + start:this.UI.button({top:4,center:this.CF.control.center,left:this.CF.control.left,bg:'green',width:this.CF.control.width,content:'Start'}), + stop:this.UI.button({top:8,center:this.CF.control.center,left:this.CF.control.left,bg:'lightgrey',width:this.CF.control.width,content:'Stop'}), + connect:this.UI.button({top:12,left:this.CF.control.left2,bg:'blue',width:this.CF.control.width2,content:'Connect'}), + reset:this.UI.button({top:12,right:this.CF.control.right2,bg:'blue',width:this.CF.control.width2,content:'Reset'}), + }, + info1:this.UI.info({ + left:this.CF.control.left, + center:this.CF.control.center, + top:16, + width:this.CF.control.width, + height:this.CF.control.info1.height, + wrap:true, + label:'Status' + }), + labels:{ + top:this.UI.label({center:true,top:1,content:'Control'}), + } + }, + classes:{ + buttons:{ + load:this.UI.button({top:4,left:this.CF.classes.left2,bg:'green',width:this.CF.classes.width2,content:'Load'}), + execute:this.UI.button({top:4,right:this.CF.classes.right2,bg:'blue',width:this.CF.classes.width2,content:'Execute'}), + create:this.UI.button({top:8,center:this.CF.classes.center,left:this.CF.classes.left,bg:this.styles.button.black,width:this.CF.classes.width,content:'Create'}), + }, + checkboxes:{ + level0:this.UI.radiobutton({left:'55%',top:17,text:'0',value:false,group:20}), + level1:this.UI.radiobutton({left:'55%',top:19,text:'1',value:true,group:20}), + level2:this.UI.radiobutton({left:'75%',top:17,text:'2',value:false,group:20}), + level3:this.UI.radiobutton({left:'75%',top:19,text:'3',value:false,group:20}) + }, + labels:{ + top:this.UI.label({center:this.CF.classes.labels.center,right:this.CF.classes.labels.right,top:1,content:this.CF.classes.labels.top}), + level:this.UI.label({left:'55%',top:15,content:'Level'}), + }, + inputs:{ + arguments:this.UI.input({ + top:12, + right:this.CF.classes.right2, + width:this.CF.classes.width2, + label:'Arguments', + value:'{}' + }), + }, + lists:{ + classes:this.UI.list({ + top:12, + left:this.CF.classes.left2, + height:this.UI.screen.height-16, + width:this.CF.classes.width2, + label:'Classes', + depth:1 + }), + } + }, + stats:{ + buttons:{ + back:this.UI.button({left:1,content:'<< Menu'}), + explorer:this.UI.button({right:1,content:'Explorer'}), + }, + infos:{ + mem:this.UI.info({top:4,left:this.CF.stats.left,width:this.CF.stats.width,label:'Memory'}), + com:this.UI.info({top:8,left:this.CF.stats.left,width:this.CF.stats.width,label:'Communication'}), + }, + labels:{ + top:this.UI.label({ + center:this.CF.stats.labels.center, + right:this.CF.stats.labels.right, + top:1, + content:this.CF.stats.labels.top + }), + }, + tree1:this.UI.tree({top:12, + left:this.CF.stats.left, + width:this.CF.stats.width, + height:self.UI.screen.height-16, + label:'System', + arrows:{up:'[-]',down:'[+]',width:3,height:1,fg:'red',bg:'default'}}) + }, + explorer:{ + buttons:{ + back:this.UI.button({left:1,content:'<< Info'}), + killall:this.UI.button({left:this.CF.explorer.left,top:4,content:'KILL All'}), + kill:this.UI.button({right:this.CF.explorer.right,top:4,content:'KILL'}), + }, + labels:{ + top:this.UI.label({ + center:this.CF.explorer.labels.center, + right:this.CF.explorer.labels.right, + top:1, + content:this.CF.explorer.labels.top + }), + }, + tree1:this.UI.tree({top:8, + left:this.CF.explorer.left, + width:this.CF.explorer.width, + height:self.UI.screen.height-12, + label:'Agents', + arrows:{up:'[-]',down:'[+]',width:3,height:1,fg:'red',bg:'default'}}) + }, + log1:this.UI.log({ + left:this.CF.log1.left, + top:4, + width:this.CF.log1.width, + label:'Logging', + arrows:{up:'[-]',down:'[+]',width:3,height:1,fg:'red',bg:'default'} + }), + pages:{ + } + } + + this.dialog = this.CS.dialog; + + this.info = this.CS.info; + this.info.setValue('Not started. Not connected. Screen '+this.UI.screen.width+'x'+this.UI.screen.height); + + function set(label,flag) { + switch (label) { + case 'Agent ID': self.config.log.agent=flag; break; + case 'Parent ID': self.config.log.parent=flag; break; + case 'Time': self.config.log.time=flag; break; + case 'Class': self.config.log.class=flag; break; + case 'PID': self.config.logJam.pid=flag; break; + case 'Node': self.config.logJam.node=flag; break; + case 'World': self.config.logJam.world=flag; break; + case 'Time ': self.config.logJam.time=flag; break; + case 'Level': self.config.agents.level=flag; break; + } + } + + /* MENU */ + page=1; + this.CS.pages.menu=page; + + this.UI.pages[page].quit = this.CS.menu.buttons.quit; + this.CS.menu.buttons.quit.on('press', function(data) { + return self.quit(0); + }); + this.UI.pages[page].label1 = this.CS.menu.labels.top; + this.UI.pages[page].but2 = this.CS.menu.buttons.setup; + this.CS.menu.buttons.setup.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.setup); + }); + this.UI.pages[page].but3 = this.CS.menu.buttons.control; + this.CS.menu.buttons.control.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.control); + }); + this.UI.pages[page].but4 = this.CS.menu.buttons.jam; + this.CS.menu.buttons.jam.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.jam); + // if (!self.status.run) { self.dialog('You need to start JAM first!');} + }); + this.UI.pages[page].but5 = this.CS.menu.buttons.agents; + this.CS.menu.buttons.agents.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.agents); + }); + this.UI.pages[page].but6 = this.CS.menu.buttons.logging; + this.CS.menu.buttons.logging.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.logging); + }); + this.UI.pages[page].next=page+1; + + /* SETUP (1) */ + page=2; + this.CS.pages.setup=page; + this.UI.pages[page].but1 = this.CS.setup.buttons.menu; + this.CS.setup.buttons.menu.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + }); + if (this.UI.layout.size != 'large') { + this.UI.pages[page].but2 = this.CS.setup.buttons.more1; + this.CS.setup.buttons.more1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('next'); + }); + } + this.UI.pages[page].label1 = this.CS.setup.labels.top1; + this.UI.pages[page].input1 = this.CS.setup.inputs.remoteip; + this.UI.pages[page].input2 = this.CS.setup.inputs.remoteipp; + this.UI.pages[page].input3 = this.CS.setup.inputs.localip; + this.UI.pages[page].input4 = this.CS.setup.inputs.protect; + this.UI.pages[page].label2 = this.CS.setup.labels.input; + if (!this.config.security) this.CS.setup.inputs.protect.noshow=true; + + this.CS.setup.inputs.remoteip.on('set content',function () { + var p=self.CS.setup.labels.input.getContent(); + self.links[p].address=self.CS.setup.inputs.remoteip.getValue(); + }); + this.CS.setup.inputs.remoteipp.on('set content',function () { + var p=self.CS.setup.labels.input.getContent(); + self.links[p].port=Number(self.CS.setup.inputs.remoteipp.getValue()); + }); + this.CS.setup.inputs.localip.on('set content',function () { + var p=self.CS.setup.labels.input.getContent(), + v=self.CS.setup.inputs.localip.getValue(); + + self.links[p].local=v; + if (p.indexOf('IP')==0) // All IP ports share same local IP listening port + for(p in self.links) + if (p.indexOf('IP')==0) self.links[p].local=v; + }); + x=this.CF.setup.checkboxes.x0,y=this.CF.setup.checkboxes.y0; + for (p in this.links) { + function make(p) { + self.UI.pages[page][p]=self.UI.checkbox({left:x,top:y,text:p,value:self.links[p].enable}); + if (!self.UI.layout.small) { + if (p.indexOf('IP')==0) { + self.UI.pages[page][p+'-proto-udp']=self.UI.radiobutton({left:x+10,top:y,text:'UDP',value:true,group:p,hidden:!self.config.expert}); + self.UI.pages[page][p+'-proto-http']=self.UI.radiobutton({left:x+18,top:y,text:'HTTP',value:false,group:p,hidden:!self.config.expert}); + } + } + self.UI.pages[page][p].on('check',function () { + self.CS.setup.labels.input.setValue(p); + self.CS.setup.inputs.remoteip.setValue(self.links[p].address||''); + self.CS.setup.inputs.remoteipp.setValue(String(self.links[p].port||'')); + self.CS.setup.inputs.localip.setValue(String(self.links[p].local||'*')); + self.links[p].enable=true; + }); + self.UI.pages[page][p].on('uncheck',function () { + self.CS.setup.labels.input.setValue(p); + self.CS.setup.inputs.remoteip.setValue(self.links[p].address||''); + self.CS.setup.inputs.remoteipp.setValue(String(self.links[p].port||'')); + self.CS.setup.inputs.localip.setValue(String(self.links[p].local||'*')); + self.links[p].enable=false; + }); + } + make(p); + y += 2; + if (y==this.CF.setup.checkboxes.y1) x=this.CF.setup.checkboxes.x1,y=this.CF.setup.checkboxes.y0; + } + this.UI.pages[page].prev=page-1; + + if (this.UI.layout.small) { + /***** SMALL *******/ + this.UI.pages[page].next=3; + /* SETUP (2) */ + page=3 + this.CS.pages.setup2=page; + this.UI.pages[page].but1 = this.CS.setup.buttons.less1; + this.UI.pages[page].label1 = this.CS.setup.labels.top2; + this.CS.setup.buttons.less1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + }); + this.UI.pages[page].but2 = this.CS.setup.buttons.more2; + this.CS.setup.buttons.more2.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('next'); + }); + this.UI.pages[page].label2 = this.CS.setup.labels.protocol; + this.UI.pages[page].checkbox21 = this.CS.setup.checkboxes.http; + this.UI.pages[page].checkbox22 = this.CS.setup.checkboxes.udp; + this.UI.pages[page].checkbox23 = this.CS.setup.checkboxes.autoconnect; + this.CS.setup.checkboxes.autoconnect.on('check',function () {self.config.autoconnect=true}); + this.CS.setup.checkboxes.autoconnect.on('uncheck',function () {self.config.autoconnect=false}); + + this.UI.pages[page].label3 = this.CS.setup.labels.agentflags; + this.UI.pages[page].checkbox31 = this.CS.setup.checkboxes.agentid; + this.UI.pages[page].checkbox32 = this.CS.setup.checkboxes.parentid; + this.UI.pages[page].checkbox33 = this.CS.setup.checkboxes.agenttime; + this.UI.pages[page].checkbox34 = this.CS.setup.checkboxes.agentclass; + + this.UI.pages[page].prev=page-1; + this.UI.pages[page].next=page+1; + /* SETUP (3) */ + + page=4; + this.CS.pages.setup3=page; + this.UI.pages[page].but1 = this.CS.setup.buttons.less2; + this.UI.pages[page].label1 = this.CS.setup.labels.top23; + this.CS.setup.buttons.less2.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + }); + this.UI.pages[page].but2 = this.CS.setup.buttons.more3; + this.CS.setup.buttons.more3.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('next'); + }); + + this.UI.pages[page].checkbox5 = this.CS.setup.checkboxes.softkey; + this.CS.setup.checkboxes.softkey.on('check',function () {self.UI.options.keyboard=self.config.keyboard=true}); + this.CS.setup.checkboxes.softkey.on('uncheck',function () {self.UI.options.keyboard=self.config.keyboard=false}); + + this.UI.pages[page].checkbox6 = this.CS.setup.checkboxes.verbose; + this.CS.setup.checkboxes.verbose.on('check',function () {self.options.verbose=2}); + this.CS.setup.checkboxes.verbose.on('uncheck',function () {self.options.verbose=1}); + + this.UI.pages[page].checkbox7 = this.CS.setup.checkboxes.simple; + this.CS.setup.checkboxes.simple.on('check',function () {self.config.simple=true}); + this.CS.setup.checkboxes.simple.on('uncheck',function () {self.config.simple=false}); + + this.UI.pages[page].checkbox8 = this.CS.setup.checkboxes.security; + this.CS.setup.checkboxes.security.on('check',function () {self.config.security=true}); + this.CS.setup.checkboxes.security.on('uncheck',function () {self.config.security=false}); + + this.UI.pages[page].label4 = this.CS.setup.labels.messageflags; + this.UI.pages[page].checkbox41 = this.CS.setup.checkboxes.msgpid; + this.UI.pages[page].checkbox42 = this.CS.setup.checkboxes.msgnode; + this.UI.pages[page].checkbox43 = this.CS.setup.checkboxes.msgworld; + this.UI.pages[page].checkbox44 = this.CS.setup.checkboxes.msgtime; + + + this.UI.pages[page].prev=page-1; + this.UI.pages[page].next=page+1; + + /* SETUP (4) SCRIPT*/ + page++; + this.CS.pages.setup4=page; + this.UI.pages[page].but1 = this.CS.setup.buttons.less3; + this.UI.pages[page].label1 = this.CS.setup.labels.top3; + this.CS.setup.buttons.less3.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + }); + this.UI.pages[page].input1 = this.CS.setup.inputs.script; + this.UI.pages[page].input1.on('set content',function () { + self.config.script = self.CS.setup.inputs.script.getContent(); + }); + this.UI.pages[page].prev=page-1; + + } else if (this.UI.layout.normal) { + /***** NORMAL *******/ + this.UI.pages[page].next=page+1; + /* SETUP (2) */ + page=3; + this.CS.pages.setup2=page; + this.UI.pages[page].but1 = this.CS.setup.buttons.less1; + this.CS.setup.buttons.less1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + }); + this.UI.pages[page].but2 = this.CS.setup.buttons.more3; + this.CS.setup.buttons.more3.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('next'); + }); + this.UI.pages[page].label1 = this.CS.setup.labels.top2; + + this.UI.pages[page].label2 = this.CS.setup.labels.protocol; + this.UI.pages[page].checkbox21 = this.CS.setup.checkboxes.http; + this.UI.pages[page].checkbox22 = this.CS.setup.checkboxes.udp; + this.UI.pages[page].checkbox23 = this.CS.setup.checkboxes.autoconnect; + this.CS.setup.checkboxes.autoconnect.on('check',function () {self.config.autoconnect=true}); + this.CS.setup.checkboxes.autoconnect.on('uncheck',function () {self.config.autoconnect=false}); + + if (this.config.expert) { + this.CS.setup.labels.protocol.noshow=true; + this.CS.setup.checkboxes.http.noshow=true; + this.CS.setup.checkboxes.udp.noshow=true; + } + + this.UI.pages[page].label3 = this.CS.setup.labels.agentflags; + this.UI.pages[page].checkbox31 = this.CS.setup.checkboxes.agentid; + this.UI.pages[page].checkbox32 = this.CS.setup.checkboxes.parentid; + this.UI.pages[page].checkbox33 = this.CS.setup.checkboxes.agenttime; + this.UI.pages[page].checkbox34 = this.CS.setup.checkboxes.agentclass; + + this.UI.pages[page].label4 = this.CS.setup.labels.messageflags; + this.UI.pages[page].checkbox41 = this.CS.setup.checkboxes.msgpid; + this.UI.pages[page].checkbox42 = this.CS.setup.checkboxes.msgnode; + this.UI.pages[page].checkbox43 = this.CS.setup.checkboxes.msgworld; + this.UI.pages[page].checkbox44 = this.CS.setup.checkboxes.msgtime; + + this.UI.pages[page].checkbox5 = this.CS.setup.checkboxes.expert; + this.CS.setup.checkboxes.expert.on('check',function () { + self.config.expert=true; + for (var p in self.links) { + if (p.indexOf('IP')==0) { + self.UI.pages[self.CS.pages.setup][p+'-proto-udp'].noshow=false; + self.UI.pages[self.CS.pages.setup][p+'-proto-http'].noshow=false; + } + } + self.CS.setup.labels.protocol.noshow=true; + self.CS.setup.checkboxes.udp.noshow=true; + self.CS.setup.checkboxes.http.noshow=true; + }); + this.CS.setup.checkboxes.expert.on('uncheck',function () { + self.config.expert=false; + for (var p in self.links) { + if (p.indexOf('IP')==0) { + self.UI.pages[self.CS.pages.setup][p+'-proto-udp'].noshow=true; + self.UI.pages[self.CS.pages.setup][p+'-proto-http'].noshow=true; + } + } + self.CS.setup.labels.protocol.noshow=false; + self.CS.setup.checkboxes.udp.noshow=false; + self.CS.setup.checkboxes.http.noshow=false; + }); + + this.UI.pages[page].checkbox6 = this.CS.setup.checkboxes.softkey; + this.CS.setup.checkboxes.softkey.on('check',function () {self.UI.options.keyboard=self.config.keyboard=true}); + this.CS.setup.checkboxes.softkey.on('uncheck',function () {self.UI.options.keyboard=self.config.keyboard=false}); + + this.UI.pages[page].checkbox7 = this.CS.setup.checkboxes.verbose; + this.CS.setup.checkboxes.verbose.on('check',function () {self.options.verbose=2}); + this.CS.setup.checkboxes.verbose.on('uncheck',function () {self.options.verbose=1}); + + this.UI.pages[page].checkbox8 = this.CS.setup.checkboxes.security; + this.CS.setup.checkboxes.security.on('check',function () { + self.config.security=true; + self.CS.setup.inputs.protect.noshow=false; + }); + this.CS.setup.checkboxes.security.on('uncheck',function () { + self.config.security=false; + self.CS.setup.inputs.protect.noshow=true; + }); + this.UI.pages[page].checkbox9 = this.CS.setup.checkboxes.sensors; + this.CS.setup.checkboxes.sensors.on('check',function () { + self.config.sensors=true; + }); + this.CS.setup.checkboxes.sensors.on('uncheck',function () { + self.config.sensors=false; + }); + this.UI.pages[page].checkbox10 = this.CS.setup.checkboxes.simple; + this.CS.setup.checkboxes.simple.on('check',function () { + self.config.simple=true; + }); + this.CS.setup.checkboxes.simple.on('uncheck',function () { + self.config.simple=false; + }); + + for(i=1;i<=4;i++) { + this.UI.pages[page]['checkbox3'+i].on('check',function (arg) {set(arg.text,true)}); + this.UI.pages[page]['checkbox3'+i].on('uncheck',function (arg) {set(arg.text,false)}); + this.UI.pages[page]['checkbox4'+i].on('check',function (arg) {set(arg.text,true)}); + this.UI.pages[page]['checkbox4'+i].on('uncheck',function (arg) {set(arg.text,false)}); + } + + this.UI.pages[page].prev=page-1; + this.UI.pages[page].next=page+1; + /* SETUP (3) SCRIPT*/ + page++; + this.CS.pages.setup3=page; + this.UI.pages[page].but1 = this.CS.setup.buttons.less3; + this.UI.pages[page].label1 = this.CS.setup.labels.top3; + this.CS.setup.buttons.less3.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + }); + this.UI.pages[page].input1 = this.CS.setup.inputs.script; + this.UI.pages[page].input1.on('set content',function () { + self.config.script = self.CS.setup.inputs.script.getContent(); + }); + this.UI.pages[page].prev=page-1; + + } else { + /***** BIG *******/ + // TODO BIG LAYOUT + + } + + /* CONTROL */ + page++; + this.CS.pages.control=page; + this.UI.pages[page].but1 = this.UI.button({left:1,content:'<< Menu'}); + this.UI.pages[page].but1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(1); + }); + + if (process.platform === 'android') { + // Hide keyboard button + this.UI.pages[page].but1X = this.UI.button({right:1,content:'Hide KB'}); + this.UI.pages[page].but1X.on('press', function(data) { + if (Proc) Proc.exec('input keyevent 4', function (err,stdout,stderr) { + self.log('Hide KB: '+err+'/'+stdout+'/'+stderr); + }); + }); + } + + this.UI.pages[page].label1 = this.CS.control.labels.top; + this.UI.pages[page].but2 = this.CS.control.buttons.start; + this.UI.pages[page].but2.on('press', function(data) { + if (!self.run) { + if (!self.status.initialized) self.initJAM(); + self.startJAM(); + } + self.update('status'); + self.UI.pages[self.CS.pages.control].but2.setStyle({bg:'lightgrey'}); + self.UI.pages[self.CS.pages.control].but3.setStyle({bg:'red'}); + }); + this.UI.pages[page].but3 = this.CS.control.buttons.stop; + this.UI.pages[page].but3.on('press', function(data) { + if (self.run) { + self.stopJAM(); + } + self.update('status'); + self.UI.pages[self.CS.pages.control].but2.setStyle({bg:'green'}); + self.UI.pages[self.CS.pages.control].but3.setStyle({bg:'lightgrey'}); + }); + this.UI.pages[page].but4 = this.CS.control.buttons.connect; + this.UI.pages[page].but4.on('press', function(data) { + self.connect(); + self.update('status'); + }); + this.UI.pages[page].but5 = this.CS.control.buttons.reset; + this.UI.pages[page].but5.on('press', function(data) { + if (self.run) { + self.stopJAM(); + } + if (self.jam) self.jam=undefined,self.status.initialized=false; + self.update('status'); + }); + this.UI.pages[page].info1 = this.CS.control.info1; + this.UI.pages[page].info1.setValue('Not connected.'); + + this.UI.pages[page].prev=this.CS.pages.menu; + + /* JAM */ + page++; + this.CS.pages.jam=page; + this.UI.pages[page].but1 = this.UI.button({left:1,content:'<< Menu'}); + this.UI.pages[page].but1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.menu); + }); + this.UI.pages[page].label1 = this.UI.label({center:true,top:1,content:'JAM'}); + + this.UI.pages[page].info1 = this.UI.info({top:4,left:4,width:self.UI.screen.width-8,label:'JAM World'}); + this.UI.pages[page].info2 = this.UI.info({top:8,left:4,width:self.UI.screen.width-8,label:'JAM Node'}); + this.UI.pages[page].info3 = this.UI.info({top:12,left:4,width:self.UI.screen.width-8,label:'JAM Domain'}); + this.UI.pages[page].info4 = this.UI.info({top:16,left:4,width:self.UI.screen.width-8,label:'JAM Status'}); + + this.UI.pages[page].info1.setValue(this.config.worldname); + this.UI.pages[page].info2.setValue(this.config.nodename); + this.UI.pages[page].info3.setValue(this.config.domain); + this.UI.pages[page].info4.setValue('Not started.'); + + this.UI.pages[page].but2 = this.UI.button({right:1,content:'Info'}); + this.UI.pages[page].but2.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.stats); + + }); + this.UI.pages[page].prev=this.CS.pages.menu; + this.UI.pages[page].next=page+1; + + /* STATISTICS */ + page++; + this.CS.pages.stats=page; + this.UI.pages[page].but1 = this.CS.stats.buttons.back; + this.CS.stats.buttons.back.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.jam); + }); + this.UI.pages[page].but2 = this.CS.stats.buttons.explorer; + this.CS.stats.buttons.explorer.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('next'); + }); + this.UI.pages[page].label1 = this.CS.stats.labels.top; + + this.UI.pages[page].info1 = this.CS.stats.infos.mem; + this.UI.pages[page].info2 = this.CS.stats.infos.com; + this.UI.pages[page].tree1 = this.CS.stats.tree1; + this.CS.stats.tree1.update({ + mem:0, + heap:0, + }); + function updateStatTree (element) { + var mem=process.memoryUsage(), + stats={ + mem:{ + _value:mem.rss, + // update beefore branch extend + _update:function (data) {data._value=process.memoryUsage().rss} + }, + heap:{ + _value:mem.heapUsed, + // update before branch extend + _update:function (data) {data._value=process.memoryUsage().heapUsed} + } + }, + p,q,node,id,pro, + sensor,sensors=process.sensor && process.sensor.info(); + var node = self.jam?self.jam.stats('node'):undefined; + + if (node) { + stats.node={}; + for(p in node) { + stats.node[p]={ + _value : node[p], + _update:(function (p) { return function (data) { data._value=self.jam.stats('node')[p] }})(p) + } + } + } + if (self.config.sensors && sensors) { + stats.sensors={}; + for(p in sensors) { + sensor=sensors[p]; + stats.sensors[sensor]=(function (s) { + return { + _value:process.sensor.read(s), + _update:function (data) { data._value = process.sensor.read(s)} + }})(typeof sensor == 'string'?sensor:sensor[2]); + } + } + if (element) element=stats; + if (self.jam) { + node=self.jam.world.nodes[0]; + stats.connections={}; + for(q in node.connections) { + if (node.connections[q]) stats.connections[q]={count:node.connections[q].count()+' Bytes'}; + } + stats.agents={}; + for(q in node.processes.table) { + if (!node.processes.table[q]) continue; + pro=node.processes.table[q]; + id=pro.agent.id; + stats.agents[id]={pid:pro.pid,class:pro.agent.ac,time:pro.consumed,level:pro.level}; + } + } + stats._update=updateStatTree; + if (!element) self.UI.pages[self.CS.pages.stats].tree1.update(stats); + } + this.UI.pages.on(page,'load',function () { + var mem=process.memoryUsage(); + self.UI.pages[self.CS.pages.stats].info1.update('Total: '+String(MB(mem.rss))+' MB, Heap: '+String(MB(mem.heapUsed))+' MB'); + self.UI.pages[self.CS.pages.stats].info2.update('0 MB'); + updateStatTree(); + }); + this.UI.pages[page].prev=this.CS.pages.jam; + this.UI.pages[page].next=page+1; + + /* EXPLORER */ + page++; + this.CS.pages.explorer=page; + this.UI.pages[page].but1 = this.CS.explorer.buttons.back; + this.CS.explorer.buttons.back.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.stats); + }); + this.UI.pages[page].but2 = this.CS.explorer.buttons.killall; + this.CS.explorer.buttons.killall.on('press', function(data) { + if (self.jam) self.jam.kill('*'); + updateAdminTree(); + }); + this.UI.pages[page].but3 = this.CS.explorer.buttons.kill; + this.CS.explorer.buttons.kill.on('press', function(data) { + // TODO kill selected agent + updateAdminTree(); + }); + + this.UI.pages[page].label1 = this.CS.explorer.labels.top; + this.UI.pages[page].prev=this.CS.pages.stats; + this.UI.pages[page].tree1 = this.CS.explorer.tree1; + var _test=0; + function updateAgent(node,id) { + return function (data) { + var p,pro=node.getAgentProcess(id); + var pro=node.getAgentProcess(id); + if (pro) { + for(p in pro.agent) data[p]=pro.agent[p]; + } else for(p in data) delete data[p]; + } + } + function updateAdminTree (element) { + var stats={},p,q,node,id,pro; + + if (element) element=stats; + if (self.jam) { + node=self.jam.world.nodes[0]; + for(q in node.processes.table) { + if (!node.processes.table[q]) continue; + pro=node.processes.table[q]; + id=pro.agent.ac+'.'+pro.agent.id+' (L'+pro.level+' T'+pro.consumed+')'; + stats[id]={}; + stats[id]._update=updateAgent(node,pro.agent.id); + for(p in pro.agent) { + stats[id][p]=pro.agent[p]; + } + } + } + stats._update=updateAdminTree; + if (!element) self.UI.pages[self.CS.pages.explorer].tree1.update(stats); + } + this.UI.pages.on(page,'load',function () { + updateAdminTree(); + }); + + /* AGENTS */ + page++; + this.CS.pages.agents=page; + this.UI.pages[page].but1 = this.UI.button({left:1,content:'<< Menu'}); + this.UI.pages[page].but1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.menu); + }); + this.UI.pages[page].but2 = this.UI.button({right:1,content:'Config'}); + this.UI.pages[page].but2.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('next'); + }); + this.UI.pages[page].label1 = this.UI.label({center:true,top:1,content:'Agents'}); + this.UI.pages[page].but3 = this.CS.agents.buttons.clear; + this.UI.pages[page].but3.on('press', function(data) { + self.msgWin.clear(); + }); + this.UI.pages[page].log1 = this.CS.agents.log1; + this.UI.pages[page].prev=this.CS.pages.menu; + + this.msgWin = this.CS.agents.log1; + this.log2('Agent message window ready.'); + + /* CLASSES */ + page++; + this.CS.pages.classes=page; + this.UI.pages[page].label1 = this.CS.classes.labels.top; + this.UI.pages[page].but1 = this.UI.button({left:1,content:'<< Agents'}); + this.UI.pages[page].but1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + }); + + this.UI.pages[page].but2 = this.CS.classes.buttons.load; + this.UI.pages[page].but3 = this.CS.classes.buttons.execute; + this.CS.classes.buttons.load.on('press', function(data) { + var status; + if (self.UI.pages[self.CS.pages.classes].fm && !self.UI.pages[self.CS.pages.classes].fm.hidden) { + return + }; + if (!self.UI.pages[self.CS.pages.classes].fm) { + self.UI.pages[self.CS.pages.classes].fm = + self.UI.fileManager({ + cwd:process.env.CWD||process.env.PWD, + parent:this.screen, + top:self.CF.fm.top, + hidden:true, + autohide:true, + width:self.CF.fm.width, + height:self.CF.fm.height, + input:{mutable:true}, + box:{}, + arrows:{up:'[-]',down:'[+]',width:3,height:1} + }); + self.UI.pages[self.CS.pages.classes].fm.refresh(); + self.UI.pages[self.CS.pages.classes].fm.on('file',function (file) { + self.loadClassFile(file); + }); + } + self.UI.pages[self.CS.pages.classes].fm.show(); + self.UI.pages[self.CS.pages.classes].fm.focus(); + }); + this.CS.classes.buttons.execute.on('press', function(data) { + var status; + if (self.UI.pages[self.CS.pages.classes].fm && !self.UI.pages[self.CS.pages.classes].fm.hidden) { + return + }; + if (!self.UI.pages[self.CS.pages.classes].fm) { + self.UI.pages[self.CS.pages.classes].fm = + self.UI.fileManager({ + cwd:process.env.CWD||process.env.PWD, + parent:this.screen, + top:self.CF.fm.top, + hidden:true, + autohide:true, + width:self.CF.fm.width, + height:self.CF.fm.height, + input:{mutable:true}, + box:{}, + arrows:{up:'[-]',down:'[+]',width:3,height:1} + }); + self.UI.pages[self.CS.pages.classes].fm.refresh(); + self.UI.pages[self.CS.pages.classes].fm.on('file',function (file) { + }); + } + self.UI.pages[self.CS.pages.classes].fm.show(); + self.UI.pages[self.CS.pages.classes].fm.focus(); + }); + this.UI.pages[page].but4 = this.CS.classes.buttons.create; + this.CS.classes.buttons.create.on('press', function(data) { + var args,cls,msg,id; + if (!self.status.run) return self.dialog('You need to start JAM first!'); + if (!self.UI.pages[self.CS.pages.classes].tree1.getSelected()) return self.dialog('No class selected!'); + cls=self.UI.pages[self.CS.pages.classes].tree1.getSelected().getContent(); + try { + eval('args='+self.UI.pages[self.CS.pages.classes].input1.getValue()); + if (!args) throw 'Invalid arguments'; + self.createAgent(cls,args,self.config.agents.level,true); + } catch (e) { + self.dialog(msg+' Error: '+e); + } + }); + + this.UI.pages[page].tree1 = this.CS.classes.lists.classes; + this.UI.pages[page].input1 = this.CS.classes.inputs.arguments; + + this.UI.pages[page].label2 = this.CS.classes.labels.level; + this.UI.pages[page].checkbox21 = this.CS.classes.checkboxes.level0; + this.UI.pages[page].checkbox22 = this.CS.classes.checkboxes.level1; + this.UI.pages[page].checkbox23 = this.CS.classes.checkboxes.level2; + this.UI.pages[page].checkbox24 = this.CS.classes.checkboxes.level3; + for(i=1;i<=4;i++) { + this.UI.pages[page]['checkbox2'+i].on('check',function (arg) {set('Level',Number(arg.text))}); + } + + this.UI.pages.on(page,'load',function() { + self.UI.pages[self.CS.pages.classes].tree1.set(self.classes); + }); + this.UI.pages[page-1].next=page; + this.UI.pages[page].prev=page-1; + + /* LOGGING */ + page++; + this.CS.pages.logging=page; + this.UI.pages[page].but1 = this.UI.button({left:1,content:'<< Menu'}); + this.UI.pages[page].but1.on('press', function(data) { + self.UI.pages.hide('this'); + self.UI.pages.show(1); + }); + this.UI.pages[page].but2 = this.UI.button({right:1,content:'Clear',bg:'green'}); + this.UI.pages[page].but2.on('press', function(data) { + self.logWin.clear(); + }); + this.UI.pages[page].label1 = this.UI.label({center:true,top:1,content:'Logging'}); + this.UI.pages[page].log1 = this.CS.log1; + + this.logWin = this.CS.log1; + this.log('JAMapp Version '+options.version+'. (c) Dr. Stefan Bosse'); + + this.UI.pages[page].prev=this.CS.pages.menu; + + this.UI.pages.show(1); + for(i=2;i<=20;i++) this.UI.pages.hide(i); + + this.info.setValue('Not connected. Not started. Screen '+ + this.UI.screen.width+'x'+this.UI.screen.height+ + ' '+(this.UI.layout.small?'S':'N')+' '+process.platform); + //console.log(this.pages[1]); + + this.UI.screen.key(['escape', 'q', 'C-c'], function(ch, key) { + return self.quit(0); + }); + + this.UI.screen.key(['left','right'], function(ch, key) { + if (key.name=='right' && self.UI.pages[self.UI.page].next){ + if (self.UI.page==self.CS.pages.menu) { + switch (self.CS.menu.selected) { + case -1: + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.setup); + break; + case 0: + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.control); + break; + case 1: + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.jam); + break; + case 2: + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.agents); + break; + case 3: + self.UI.pages.hide('this'); + self.UI.pages.show(self.CS.pages.logging); + break; + } + } else { + self.UI.pages.hide('this'); + self.UI.pages.show('next'); + } + } else if (key.name=='left' && self.UI.pages[self.UI.page].prev) { + self.UI.pages.hide('this'); + self.UI.pages.show('prev'); + } + }); + this.CS.menu.selected=-1; + this.UI.screen.key(['up','down'], function(ch, key) { + if (key.name=='up' && self.UI.page==self.CS.pages.menu && self.CS.menu.selected >= 0){ + self.CS.menu.selected--; + switch (self.CS.menu.selected) { + case -1: + self.CS.menu.buttons.control.setStyle({bg:'blue'}); + break; + case 0: + self.CS.menu.buttons.jam.setStyle({bg:'blue'}); + self.CS.menu.buttons.control.setStyle({bg:'red'}); + break; + case 1: + self.CS.menu.buttons.agents.setStyle({bg:'blue'}); + self.CS.menu.buttons.jam.setStyle({bg:'red'}); + break; + case 2: + self.CS.menu.buttons.logging.setStyle({bg:'blue'}); + self.CS.menu.buttons.agents.setStyle({bg:'red'}); + break; + } + self.UI.screen.render(); + } else if (key.name=='down' && self.UI.page==self.CS.pages.menu && self.CS.menu.selected < 3) { + self.CS.menu.selected++; + switch (self.CS.menu.selected) { + case 0: + self.CS.menu.buttons.control.setStyle({bg:'red'}); + break; + case 1: + self.CS.menu.buttons.control.setStyle({bg:'blue'}); + self.CS.menu.buttons.jam.setStyle({bg:'red'}); + break; + case 2: + self.CS.menu.buttons.jam.setStyle({bg:'blue'}); + self.CS.menu.buttons.agents.setStyle({bg:'red'}); + break; + case 3: + self.CS.menu.buttons.agents.setStyle({bg:'blue'}); + self.CS.menu.buttons.logging.setStyle({bg:'red'}); + break; + } + self.UI.screen.render(); + } + }); +} + +appTerm.prototype.start = function () { + var self=this; + if (this.config.mode!='server') this.UI.start(); + else { + if (!self.run) { + if (!self.status.initialized) self.initJAM(); + self.startJAM(); + } + } + //setTimeout(function (){process.exit(0)},10000); +} + + +appTerm.prototype.startScript = function (script) { + var self=this; + function load(file) { + self.out('[SCRIPT] Loading agent class file '+file); + self.loadClassFile(file); + } + function create(cls,args,level) { + self.out('[SCRIPT] Creating agent '+cls+'()'); + self.createAgent(cls,args,level); + } + try { + eval(script); + } catch (e) { + self.out('Script execution failed: '+e); + } +} + +appTerm.prototype.startJAM = function () { + var self=this; + this.run=true; + // Start up JAM + if (this.config.mode!='server') this.UI.pages[this.CS.pages.control].info1.setValue('JAM starting ..'); + this.jam.start(function () { + self.out('JAM started.'); + if (self.config.mode!='server') { + self.UI.pages[self.CS.pages.control].info1.setValue('JAM and NET started.'); + self.UI.pages[self.CS.pages.jam].info4.setValue('JAM running.'); + } + self.status.run=true; + self.update('status'); + if (self.config.autoconnect) + self.connect(); + // Execute start script + self.startScript(self.config.script); + }); + +} + +appTerm.prototype.stopJAM = function () { + this.run=false; + // Stop JAM + this.UI.pages[this.CS.pages.control].info1.setValue('JAM stopping ..'); + this.jam.stop(); + this.status.run=false; + this.update('status'); + if (this.config.mode!='server') { + this.UI.pages[this.CS.pages.control].info1.setValue('JAM and NET stopped.'); + this.UI.pages[this.CS.pages.jam].info4.setValue('JAM stopped.'); + } + this.out('JAM stopped.'); +} + +appTerm.prototype.update = function (what) { + var s,sep; + switch (what) { + case 'status': + s=''; + s += this.status.initialized?'Initialized.':'Not initialized.'; + s += this.status.run?' Running.':' Not running.'; + s += this.status.connected?' Connected.':' Not connected.'; + s += this.status.connecting?' Connecting ..':''; + s += this.status.error?(' Error:'+this.status.error):''; + if (this.config.mode!='server') this.info.setValue(s); + break; + case true: + // full update + break; + } +} + +var App = function(options) { + var obj=none; + obj = new appTerm(options); + return obj; +} + +var JA = App(); +JA.init (); +JA.start (); +