Try   HackMD

How to Generate BlocklyDuino Block (如何生成Block)

進入BlocklyDuino (or BlockyDuino-for-LinkIt) \blockly 的資料夾當中

在BlocklyDuino(or BlockyDuino-for-LinkIt)\blockly中有兩個資料夾:

  • blocks
    • Blocks 資料夾下的程式碼,對應各種 Blocks,若是要新增一個 Block,則需在此新增,其中 block 的板型可依需求自行設定。
    • Block 的 code 的範例:
Blockly.Blocks['servo_read'] = {
  init: function () {
    this.setHelpUrl(Blockly.Msg.SERVO_READ_HELPURL);
    this.setColour(Blockly.Blocks.servo.HUE);
    this.appendDummyInput()
      .appendField(new Blockly.FieldImage(Blockly.Blocks.servo.image, 64, 64))
      .appendField(Blockly.Msg.SERVO_READ_TEXT1)
      .appendField(new Blockly.FieldDropdown(profile.default.digital), "PIN")
      .appendField(Blockly.Msg.SERVO_READ_TEXT2);
    this.setInputsInline(true);
    this.setOutput(true, "Number");
    this.setTooltip(Blockly.Msg.SERVO_READ_TOOLTIP);
  }
};
  • generator\arduino
    • Generator 裡面的程式碼,負責將 Blocks 資料夾下的 blocks 轉換為 Arduino code。
    • Generatro 的 code 的樣板大致如下:
Blockly.Arduino.servo_read = function() {
  var pin = this.getFieldValue('PIN');
  Blockly.Arduino.definitions_['define_servo'] = '#include <Servo.h>';
  Blockly.Arduino.definitions_['define_class_servo_'+ pin] = 'Servo myservo' + pin + ';';
  var code = 'myservo' + pin + '.read()';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Generator 會生成對應 Blocks 的 Arduino code,因此在 BlocklyDuino\blockly\Blocks 資料夾下的檔案或 function,在 Generator 端都要有一個同樣函數名稱的對應。

  • 比如:inout.js這個檔案在BlocklyDuino\blockly以及Generator/arduino都有一份同檔名但不同內文的檔案
    • 在blocky的inout.js是負責處理各個Block的外觀及功能描述
    • 在Generator的inout.js是負責把在BlocklyDuino描述的功能轉換至Arduino Code。

開始生成自己的Block

接下來,簡單講解 Block 的 code 所代表的意義。在Block中,以servo.js的讀取servo狀態為例:

Blockly.Blocks['servo_read'] = {
  init: function () {
    this.setHelpUrl(Blockly.Msg.SERVO_READ_HELPURL);    //預設值
    this.setColour(Blockly.Blocks.servo.HUE);           //預設值 
    this.appendDummyInput()                             //input
      .appendField(new Blockly.FieldImage(Blockly.Blocks.servo.image, 64, 64))
      .appendField(Blockly.Msg.SERVO_READ_TEXT1)
      .appendField(new Blockly.FieldDropdown(profile.default.digital), "PIN")
      .appendField(Blockly.Msg.SERVO_READ_TEXT2);
    this.setInputsInline(true);
    this.setOutput(true, "Number");
    this.setTooltip(Blockly.Msg.SERVO_READ_TOOLTIP);
  }
};

其中的 Blocky.Blocks['function name'] 務必要注意兩邊資料夾的名稱要相同,
而您將可以在 init:function() { code.....} 完成您要做的事情。

在 generator 的部分,仍以servo.js的讀取servo狀態為例:

Blockly.Arduino.servo_read = function() {
  var pin = this.getFieldValue('PIN');
  Blockly.Arduino.definitions_['define_servo'] = '#include <Servo.h>';
  Blockly.Arduino.definitions_['define_class_servo_'+ pin] = 'Servo myservo' + pin + ';';
  var code = 'myservo' + pin + '.read()';
  return [code, Blockly.Arduino.ORDER_ATOMIC];
};

主要Map至Arduino的Function用法: Blockly.Arduino.definitions_['function name']= 'arduino function'

其中要注意的是,
在同一個Block中,function name 的部分要避免相同的名字,否則在Map至Arduino Code中的時候將會產生後宣告的function覆蓋掉前面寫過的相同Function的情形。

關於Blockly.Arduino.ORDER_ATOMIC,則是會告訴 Blockyduino 現在即將要進到下一個 Block 而不是進到子Block運行。

Example:

  • 當item=1000 賦值完畢後,function將會return Blockly.Arduino.ORDER_ATOMIC,並開始執行下一個Block的指令。

常用的函數指令:

  • this.setHelpUrl 用於塞入網址,可以在IDE中點HELP即可進入。

  • this.setColour 塞的是Block的色調

  • this.setPreviousStatement & this.setNextStatement 決定能不能被插 & 插入Block

  • appendDummyInput() 告訴程式此處要塞字串

    • appendField 則是引導程式到字串的地方
      • 延伸用法:appendField(new Blockly.FieldDropdown(OPERATORS), 'OP');
      • 可以插入圖片 如下: .appendField(new Blockly.FieldImage(Blockly.Blocks.servo.image, 64, 64))
  • setCheck 確認型別

  • setAlign 確認邊界

  • setTooltip 是將blocky\msg資料夾中相關的Block說明訊息映射至Block中供使用者可以在IDE中參閱。

  • FieldDropdown 下拉式選單

    • 以appendField(new Blockly.FieldDropdown(OPERATORS), 'OP')為例,OPERATORS是變數名稱。在Logic裡面的範例中,OPERATOR會引導到在同一個Block的Tooltip變數中,再轉換成字串
  • setOutput 變成Data拼圖,類似數據的情形

  • Blockly.Arduino.statementToCode 對應到this.statementinput.

  • this.appendValueInput 允許你讓Data Block從右邊插入

    • .setcheck 則是要你決定輸入的狀態。
      • 可以允許多個setcheck
  • this.appendDummyInput 則是沒有讓Data Block從右邊插入的功能,但是可以讓你在下面繼續塞Block內部的字串,也不需要在appendDummyinput()裡面宣告特定的文字,更可以塞一些選項

    • Example:
    ​​​​this.appendDummyInput()
    ​​.setAlign(Blockly.ALIGN_RIGHT)
    ​​.appendField(Blockly.Msg.LINKIT_SET_LBLE_ATTRIBUTE)
    ​​.appendField(new Blockly.FieldDropdown([[Blockly.Msg.LINKIT_SET_LBLE_READ, "LBLE_READ"], [Blockly.Msg.LINKIT_SET_LBLE_WRITE, "LBLE_WRITE"], [Blockly.Msg.LINKIT_SET_LBLE_READ_WRITE, "LBLE_READ | LBLE_WRITE"]]), 'TYPE');
    

更改在BlockyDuino\Blocky\msg目錄下的js檔案:

  • message.js
    • 用途是將Block資料夾中的變數名稱對映至實際的Block上,使BlockyDuino的使用者可以知道每個Block的功能。
    • message.js的功能便是將 "CommentOut" 這段字串印至Block上
  • zn.js (位於BlockyDuino\Blocky\msg\js)
    • 同message.js,但會將資料對映的語系換成中文。

最後一步:將所有新增的Block加入category中

  • catagory.js(目錄)
    • 還要改同目錄下的js\setCategoryCharacter
    • 用途是為了生成目錄來存放Block

8.在Command line用sh make.sh去build,並將offline-editor 拖曳丟入 chrome : extension 完成。
- 注意:假如有換行字元的原因而無法成功build的時候,請改為使用: sh make0.sh