ラベル google-blockly の投稿を表示しています。 すべての投稿を表示
ラベル google-blockly の投稿を表示しています。 すべての投稿を表示

2013年6月9日日曜日

Blockly+linda.jsなこと(linda-arduino-sensorの値をとるコードを作成してみた)

(ブロックの表記は'温度計の値を読む'とかにして,内部でjsコードが正しくできあがるって方向に進めると良さげなんだろう.たぶん)
Result:



How:
配置
1. blockly(-read-only)
svn checkout http://blockly.googlecode.com/svn/trunk/ blockly-read-only
2. jquery.min.js
3. index.html (based on blockly-read-only/demos/generator/index.html)
'rpi.local'はlinda-baseが動いているマシン
<html>
    <head>
  <meta charset="utf-8">
  <title>blocky - linda</title>
  <script type="text/javascript" src="blockly-read-only/blockly_compressed.js"></script>
  <script type="text/javascript" src="blockly-read-only/en_compressed.js"></script>
  <script type="text/javascript" src="blockly-read-only/javascript_compressed.js"></script>


  <script type="text/javascript" src="./language_linda.js"></script>
  <script type="text/javascript" src="./language_utility.js"></script>
  <script src="./jquery.min.js"></script>
  <script src="http://rpi.local:5000/rocketio/linda.js"></script>
  <script>
   var linda= new Linda();
  </script>


  <style>
   body {
    background-color: white;
    font-family: sans-serif;
   }
   h1 {
    font-weight: normal;
    font-size: 140%;
   }
  </style>
 </head>
 <body>
  <p>
   <button onclick="showCode()">
    Show JavaScript
   </button>
   <button onclick="runCode()">
    Run JavaScript
   </button>
  </p>

  <div id="blocklyDiv" style="height: 480px; width: 600px;"></div>

  <xml id="toolbox" style="display: none">
   <category name="Control">
    <block type="controls_if"></block>
    <block type="controls_repeat_ext">
     <value name="TIMES">
      <block type="math_number">
       <title name="NUM">10</title>
      </block>
     </value>
    </block>
    <block type="controls_whileUntil"></block>
   </category>
   <category name="Logic">
    <block type="logic_compare"></block>
    <block type="logic_operation"></block>
    <block type="logic_negate"></block>
    <block type="logic_boolean"></block>
   </category>
   <category name="Math">
    <block type="math_number"></block>
    <block type="math_arithmetic"></block>
    <block type="math_single"></block>
   </category>
   <category name="Text">
    <block type="text"></block>
    <block type="text_length"></block>
    <block type="text_print"></block>
   </category>

   <category name="Variables" custom="VARIABLE"></category>
   <category name="List">
    <block type="lists_create_empty"></block>
    <block type="lists_create_with"></block>
    <block type="lists_repeat">
     <value name="NUM">
      <block type="math_number">
       <title name="NUM">5</title>
      </block>
     </value>
    </block>
    <block type="lists_length"></block>
    <block type="lists_isEmpty"></block>
    <block type="lists_indexOf">
     <value name="VALUE">
      <block type="variables_get">
       <title name="VAR">list</title>
      </block>
     </value>
    </block>
    <block type="lists_getIndex">
     <value name="VALUE">
      <block type="variables_get">
       <title name="VAR">list</title>
      </block>
     </value>
    </block>
    <block type="lists_setIndex">
     <value name="LIST">
      <block type="variables_get">
       <title name="VAR">list</title>
      </block>
     </value>
    </block>
    <block type="lists_getSublist">
     <value name="LIST">
      <block type="variables_get">
       <title name="VAR">list</title>
      </block>
     </value>
    </block>
   </category>
   <category name="Linda">
    <block type="linda_createTupleSpace">
     <value name="TupleSpace">
      <block type="text">
       <title name="TEXT">myhome</title>
      </block>
     </value>
    </block>
    <block type="linda_watch">
     <title name="LIST">tuple</title>
    </block>
   </category>
   <category name="Utility">
    <block type="utility_log"></block>
   </category>

  </xml>

  <script>
   Blockly.inject(document.getElementById('blocklyDiv'), {
    path: 'blockly-read-only/',
    toolbox: document.getElementById('toolbox')
   });

   function showCode() {
    // Generate JavaScript code and display it.
    Blockly.JavaScript.INFINITE_LOOP_TRAP= null;
    var code= Blockly.Generator.workspaceToCode('JavaScript');
    alert(code);
   }

   function runCode() {
    // Generate JavaScript code and run it.
    window.LoopTrap= 1000;
    Blockly.JavaScript.INFINITE_LOOP_TRAP= 'if (--window.LoopTrap == 0) throw "Infinite loop.";\n';
    var code= Blockly.Generator.workspaceToCode('JavaScript');
    Blockly.JavaScript.INFINITE_LOOP_TRAP= null;
    try {
     eval(code);
    }
    catch (e) {
     alert(e);
    }
   }
  </script>

 </body>
</html>

4. language_linda.js
if(!Blockly.Language) {
    Blockly.Language= {};
}

Blockly.Language.linda_createTupleSpace= {
 category: 'Linda',
 helpUrl: '',
 init: function() {
  this.setColour(110);
  this.setOutput(true);
  this.appendValueInput('TupleSpace').appendTitle('Create TupleSpace:')
  this.setPreviousStatement(false);
  this.setNextStatement(false);
  this.setTooltip('Create a TupleSpace.');
 }
};

Blockly.Language.linda_watch= {
 category: 'Linda',
 helpUrl: '',
 init: function() {
  this.setColour(110);
  this.appendValueInput('TupleSpace').appendTitle('TupleSpace:');
  this.appendValueInput('Tuple').appendTitle('Watch Tuple:');
  this.appendDummyInput().appendTitle('Found Tuple:').appendTitle(new Blockly.FieldVariable(null), 'LIST');
  this.appendStatementInput('DO').appendTitle('Do');
  this.setPreviousStatement(true);
  this.setNextStatement(true);
  this.setTooltip('Watch the tuple in the tuplespace.');
 }
};

Blockly.JavaScript= Blockly.Generator.get('JavaScript');

Blockly.JavaScript.linda_createTupleSpace= function() {
 var _ts= Blockly.JavaScript.valueToCode(this, 'TupleSpace', Blockly.JavaScript.ORDER_NONE) || 'test';
 var code= "new linda.TupleSpace(" + _ts + ")"
 return [code, Blockly.JavaScript.ORDER_NONE];
};

Blockly.JavaScript.linda_watch= function() {
 var _ts= Blockly.JavaScript.valueToCode(this, 'TupleSpace', Blockly.JavaScript.ORDER_NONE) || 'ts';
 var _t= Blockly.JavaScript.valueToCode(this, 'Tuple', Blockly.JavaScript.ORDER_NONE) || '["sensor"]';
 var _l= Blockly.JavaScript.variableDB_.getName(this.getTitleValue('LIST'), Blockly.Variables.NAME_TYPE) || 'list';
 var branch= Blockly.JavaScript.statementToCode(this, 'DO');
 var code= _ts + ".watch(" + _t + ", function(" + _l + "){\n";
 code+= branch;
 code+= "\n});\n";
 return [code, Blockly.JavaScript.ORDER_NONE];
}; 
5. language_utility.js
if(!Blockly.Language) {
 Blockly.Language= {};
}

Blockly.Language.utility_log= {
 category: 'Linda',
 helpUrl: '',
 init: function() {
  this.setColour(111);
  this.appendValueInput('Message').appendTitle('console.log:');
  this.setPreviousStatement(true);
  this.setNextStatement(true);
  this.setTooltip('console.log()');
 }
};

Blockly.JavaScript= Blockly.Generator.get('JavaScript');

Blockly.JavaScript.utility_log= function() {
 var _msg= Blockly.JavaScript.valueToCode(this, 'Message', Blockly.JavaScript.ORDER_NONE) || '';
 var code= "console.log(" + _msg + ")"
 return code;
}; 

2012年6月2日土曜日

'google-blockly'+'serialport-server'

  1. I used 'Serialport-server' ( http://shokai.github.com/serial­­port-server/ ).
  2. I got the google-blockly code from google code by svn.
  3. I added the 'language_device.js' in demos/maze folder. The 'language_device.js' code is in my blog.
  4. I added one line which request the 'language_device.js' to the 'frame.html' in demos/maze folder.
  5. I added some lines to the 'maze.js' in demos/maze folder. The lines code is in my blog.
    Scratch has the function about 'create a program using blocks'. Scratch has the function about 'serial port communication'. The following page describes the serial port communication between Scratch and Ardino in Japanese and English.
    Scratch+Arduino | Yengawa Systems http://www.yengawa.com/scratch_arduino

動機
コード language_device.js
if (!Blockly.Language) {
  Blockly.Language = {};
}

Blockly.JavaScript = Blockly.Generator.get('JavaScript');

Blockly.Language.device_sendValue = {
  category: 'Device',
  helpUrl: '',
  init: function() {
    this.setColour(210);
    this.addTitle('Send Value');
    var dropdown = new Blockly.FieldDropdown(function() {
      return Blockly.Language.device_sendValue.Symbol;
    });
    this.addTitle(dropdown);
    this.setTitleText(Blockly.Language.device_sendValue.Symbol[0], 1);
    this.addTitle('To Server (Addr \u201C');
    this.addTitle(new Blockly.FieldTextInput('http://localhost:8783'));
    this.addTitle('\u201D \)');
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.setTooltip('Send Value to the serialport-server');
  }
};

Blockly.Language.device_sendValue.Symbol = ['o', 'x'];

Blockly.JavaScript.device_sendValue = function() {
  var _addr= Blockly.JavaScript.quote_(this.getTitleText(3));
  var _symbol = Blockly.Language.device_sendValue.Symbol.indexOf(this.getTitleText(1));
  
  if (false) {
    var cmd= "var xhr = new XMLHttpRequest();";
    cmd+= "xhr.open('post', "+_addr+", false);";
    cmd+= "xhr.onreadystatechange = function(){";
    cmd+= "if (xhr.readyState === 4 && xhr.status === 200){";
    cmd+= "}";
    cmd+= "};";
    cmd+= "xhr.send('"+_symbol+"');\n";
    return cmd;
  }
  else {
    return (_symbol===0?"Maze.ledon();":"Maze.ledoff();")+"\n";
  }
};
  • 'Blockly.JavaScript.device_sendValue'においてMazeのアニメに合わせて動作させるために内部用のコマンドを返すようにしてあるが, 単に対応するJavascriptを返すだけならif文のthen側,cmdの値を使えばよい.(serialport-serverに'o'か'x'を送るというJavascript)
  • これをframe.htmlで定義している他のjsファイルと共に読み込ませるだけでエディタの項目に出てくる
  • 編集結果のjavascript codeを取得するには
      var code = Blockly.Generator.workspaceToCode('JavaScript');
    
    で取得できる.(引数文字列'JavaScript'とBlockly.'JavaScript'が対応付いて'Language'の関数(Blocklyの編集用オブジェクト)に対応する'JavaScript'の同名関数の返り値(文字列)の集まりが得られる)
結果
maze.jsの差分(赤色部分)
 …
Maze.animate = function() {
 …
  } else if (action == 'finish') {
    Maze.scheduleFinish();
  }
  else if (action == 'send_o') {
      var xhr = new XMLHttpRequest();
      xhr.open('post', 'http://localhost:8783', true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState === 4 && xhr.status === 200){
        }
      };
      xhr.send('o');
  }
  else if (action == 'send_x') {
      var xhr = new XMLHttpRequest();
      xhr.open('post', 'http://localhost:8783', true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState === 4 && xhr.status === 200){
        }
      };
      xhr.send('x');
  }
  
  Maze.pidList.push(window.setTimeout(Maze.animate, Maze.STEP_SPEED * 5));
};
 …
Maze.ledoff = function() {
  Maze.checkTimeout();
  Maze.path.push(['send_x', null]);
}
Maze.ledon = function() {
  Maze.checkTimeout();
  Maze.path.push(['send_o', null]);
}