diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..0b92d57 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory" : "public/components" +} diff --git a/concert_workflow_engine_blockly/bower.json b/concert_workflow_engine_blockly/bower.json index 3226b4d..89004a7 100644 --- a/concert_workflow_engine_blockly/bower.json +++ b/concert_workflow_engine_blockly/bower.json @@ -1,59 +1,21 @@ { - "name": "rocon_authoring", + "name": "workflow_engine", "version": "0.0.0", + "homepage": "https://github.com/robotics-in-concert/rocon_workflow_engine_blockly", "authors": [ "Eunsub Kim " ], - "license": "BSD", - "private": true, + "license": "MIT", "ignore": [ "**/.*", "node_modules", "bower_components", - "public/components", "test", "tests" ], "dependencies": { - "blockly": "git@github.com:google/blockly.git", - "bootstrap": "~3.3.2", - "json-editor": "~0.7.13", - "angular-ui-select": "~0.9.6", - "angular-socket-io": "~0.7.0", - "angular-ui-router": "~0.2.13", - "angular-ui-bootstrap": "~0.12.0", - "angular-bootstrap": "~0.12.0", - "x-editable": "~1.5.1", - "lodash": "~3.0.0", - "ramda": "~0.8.0", - "mousetrap": "~1.4.6", - "highlightjs": "~8.4.0", - "vkbeautify-wrapper": "*", - "angular-sanitize": "~1.3.10", - "jsonselect": "~0.2.1" - }, - "overrides": { - "jsonselect": { - "main": [ - "src/jsonselect.js" - ] - }, - "blockly": { - "main": [ - "blockly_compressed.js", - "blocks_compressed.js", - "javascript_compressed.js", - "msg/js/en.js" - ] - }, - "x-editable": { - "main": [ - "dist/bootstrap3-editable/js/bootstrap-editable.js", - "dist/bootstrap3-editable/css/bootstrap-editable.css" - ], - "dependencies": { - "bootstrap": "*" - } - } + "polymer": "Polymer/polymer#~0.5.5", + "font-roboto": "Polymer/font-roboto#~0.5.5", + "core-signals": "Polymer/core-signals#~0.5.5" } } diff --git a/concert_workflow_engine_blockly/docs/POLYMER.md b/concert_workflow_engine_blockly/docs/POLYMER.md new file mode 100644 index 0000000..dcce5e7 --- /dev/null +++ b/concert_workflow_engine_blockly/docs/POLYMER.md @@ -0,0 +1,80 @@ +Polymer components +================== + + +* polymer components 의 경로 : public/polymer_components + + + + +## Polymer component 생성 + +1. public/polymer_components 하위에 원하는 `component이름.html` 생성 (예, video.html) + +1. Grid 레이아웃을 위해 /css/rocon-component.css 를 포함 +1. components 의 내용전체를 `
` 로 감싸준다. + +1. `` 태그 안에는 원하는 내용의 스크립트 작업 +1. `rocon-compoent-wrapper` div 안에는 원하는 마크업을 작성한다. + + +### 예제 + +```html + + + + + + + + +``` + + +## Workflow Engine 과의 통신 처리 (pub/sub) + +### Publish + +Workflow Engine과에 pub 통신을 하는 부분은 rocon compoents 에서는 [core-signals](https://www.polymer-project.org/0.5/docs/elements/core-signals.html#core-signals) 로 추상화 되어 있다. + + +#### polymer components 에서 pub 하는 방법 + +* core-signals 의 fire 메서드를 이용한다. + * name : 'rocon-component' 고정 + * data : publish 할 데이터 (JSON 으로 변경되어 std_msgs/String 타입으로 전달) + +* 예제 + +```js + Polymer('rocon-button', { + handleTap: function(){ + this.fire('core-signal', {name: 'rocon-component', data: {'event': 'tap', id: this.rocon_id}}); + console.log('core signal fired'); + } +``` + + +### Subscribe + +workflow engine 에서 socket.io 의 `/ui` 채널로 전달되는 데이터로 처리한다. + +* /ui 채널로 전달되는 데이터의 필드 + * rocon_id : polymer component 의 id 값 + * attr : 변경할 attribute (예, img 태그의 src) + * value : 변경할 값. + diff --git a/concert_workflow_engine_blockly/public/css/rocon-component.css b/concert_workflow_engine_blockly/public/css/rocon-component.css new file mode 100644 index 0000000..389d430 --- /dev/null +++ b/concert_workflow_engine_blockly/public/css/rocon-component.css @@ -0,0 +1,16 @@ + +:host { + margin: 4px; + padding: 10px; + border: solid 1px #aaa; + cursor: pointer; + display: flex; + flex: 1; + align-items: center; + +} +#rocon-component-wrapper { + display: block; + flex: 1; + text-align: center; +} diff --git a/concert_workflow_engine_blockly/public/polymer_components/rocon-button.html b/concert_workflow_engine_blockly/public/polymer_components/rocon-button.html new file mode 100644 index 0000000..3f786cb --- /dev/null +++ b/concert_workflow_engine_blockly/public/polymer_components/rocon-button.html @@ -0,0 +1,33 @@ + + + + + + + + + + + diff --git a/concert_workflow_engine_blockly/public/polymer_components/rocon-text.html b/concert_workflow_engine_blockly/public/polymer_components/rocon-text.html new file mode 100644 index 0000000..46a0e13 --- /dev/null +++ b/concert_workflow_engine_blockly/public/polymer_components/rocon-text.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/concert_workflow_engine_blockly/src/engine.js b/concert_workflow_engine_blockly/src/engine.js index e6817f3..4b015bb 100644 --- a/concert_workflow_engine_blockly/src/engine.js +++ b/concert_workflow_engine_blockly/src/engine.js @@ -393,6 +393,11 @@ Engine.prototype.reload = function(){ }; +Engine.prototype.createUI = function(name, meta){ + process_send2({cmd: 'create_ui', name: name, meta: meta}); +}; + + module.exports = Engine; diff --git a/concert_workflow_engine_blockly/src/engine_manager.js b/concert_workflow_engine_blockly/src/engine_manager.js index e09a7f2..63f52d8 100644 --- a/concert_workflow_engine_blockly/src/engine_manager.js +++ b/concert_workflow_engine_blockly/src/engine_manager.js @@ -3,6 +3,7 @@ var spawn = require('child_process').spawn, Promise = require('bluebird'), Engine = require('./engine'), ResourceManager = require('./resource_manager'), + UIManager = require('./ui_manager'), util = require('util'), Requester = require('./requester').Requester, Resource = require('./requester').Resource, @@ -23,6 +24,13 @@ var EngineManager = function(io, options){ this.resource_pool_status = null; ros.once('status.ready', function(){ + ros.subscribe('to-rocon-ui', 'std_msgs/String', function(payload){ + console.log('to-rocon-ui received. payload : ', payload); + + io.of('/ui') + .emit('data', payload); + }); + ros.subscribe('/concert/scheduler/resource_pool', 'scheduler_msgs/KnownResources', function(payload){ logger.debug("POOL", payload); that.resource_pool_status = payload; @@ -36,6 +44,7 @@ var EngineManager = function(io, options){ }); + this.ui_manager = new UIManager(); this.resource_manager = new ResourceManager(ros); this.resource_manager.onAny(function(){ that.broadcastResourcesInfo(); @@ -78,7 +87,10 @@ var EngineManager = function(io, options){ } }); + }); + this.io.of('/ui').on('connection', function(socket){ + logger.info('socket.io (/ui) client connected id:%s', socket.id); }); }; @@ -335,6 +347,10 @@ EngineManager.prototype._bindEvents = function(child){ result = true break; + case 'create_ui': + result = that.ui_manager.newUI(msg.name, msg.meta); + break; + default: var action = msg.action; result = that.emit(['child', child.pid, action].join('.'), msg); diff --git a/concert_workflow_engine_blockly/src/routes.js b/concert_workflow_engine_blockly/src/routes.js index 7acab78..4cc2b2c 100644 --- a/concert_workflow_engine_blockly/src/routes.js +++ b/concert_workflow_engine_blockly/src/routes.js @@ -34,6 +34,44 @@ module.exports = function(app){ }); + app.get('/ui/:name', function(req, res){ + var name = req.params.name; + + var meta = global.engineManager.ui_manager.ui[name]; + + if(!meta){ + var el = '
no ui found.
' + }else{ + console.log(meta); + + + var _build = function(meta){ + if(meta.type == 'vertical' || meta.type == 'horizontal'){ + + if(meta.children){ + var childrenEl = _.map(meta.children, function(c){ + return _build(c); + }).join(""); + } + return '
'+childrenEl+'
'; + + }else if(meta.type == 'button'){ + return ''; + }else if(meta.type == 'text'){ + return ''; + } + + + }; + + + var el = '
'+_build(meta[0])+'
' + } + console.log(el); + + // res.send(global.engineManager.ui_manager.ui); + res.render('ui', {el:el}); + }); app.post('/api/engine/reset', function(req, res){ global.restartEngine(); diff --git a/concert_workflow_engine_blockly/src/ui_manager.js b/concert_workflow_engine_blockly/src/ui_manager.js new file mode 100644 index 0000000..7274455 --- /dev/null +++ b/concert_workflow_engine_blockly/src/ui_manager.js @@ -0,0 +1,25 @@ + +var _ = require('lodash'), + UUID = require('node-uuid'), + EventEmitter2 = require('eventemitter2').EventEmitter2; + + + +var UIManager = function(){ + this.ui = {}; + + +}; + + + +UIManager.prototype.newUI = function(name, meta){ + this.ui[name] = meta; + + console.log('ui added', name, meta); + +}; + + + +module.exports = UIManager; diff --git a/concert_workflow_engine_blockly/views/ui.html b/concert_workflow_engine_blockly/views/ui.html new file mode 100644 index 0000000..a9cf941 --- /dev/null +++ b/concert_workflow_engine_blockly/views/ui.html @@ -0,0 +1,129 @@ + + + + + + unquote + + + + + + + + + + + + + + + + + + + + + + + + + +