# How to Generate BlocklyDuino Block (如何生成Block) # 進入BlocklyDuino (or BlockyDuino-for-LinkIt) \blockly 的資料夾當中 在BlocklyDuino(or BlockyDuino-for-LinkIt)\blockly中有兩個資料夾: - blocks <!-- - 當中的資料對應的是 Blocklyduino 中可被使用的Block--> - 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 <!-- - 當中的資料對應的是對映 (Map) 在Blocklyduino所製造的程式碼至Arduino code--> - 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: ![](https://i.imgur.com/6uiGAhb.png) - 當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的功能。 - ![](https://i.imgur.com/gODX9hB.png) - 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`