/** Fix Basic Blocks ****************************************************************************************/ var ugjConsrolForDefinition = { "type": "ugj_control_for", "message0": "%{BKY_UGJ_CONTROL_FOR_TITLE}", "args0": [ { "type": "field_variable", "name": "index", "variable": "%{BKY_UGJ_CONTROL_FOR_INDEX}" }, { "type": "input_dummy" }, { "type": "input_value", "name": "from", "check": "Number" }, { "type": "input_value", "name": "to", "check": "Number" }, { "type": "input_value", "name": "by", "check": "Number" }, { "type": "field_dropdown", "name": "crease", "options": [ [ "%{BKY_UGJ_CONTROL_FOR_INCREASE}", "+" ], [ "%{BKY_UGJ_CONTROL_FOR_DECREASE}", "-" ] ] }, { "type": "input_dummy" }, { "type": "input_statement", "name": "do" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_UGJ_CONTROL_FOR_TOOLTIP}", "helpUrl": "", "style": "loop_blocks" }; Blockly.Blocks['ugj_control_for'] = { init: function () { this.jsonInit(ugjConsrolForDefinition); } }; Blockly.JavaScript['ugj_control_for'] = function (block) { var variable_index = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE); var value_from = Blockly.JavaScript.valueToCode(block, 'from', Blockly.JavaScript.ORDER_ATOMIC); var value_to = Blockly.JavaScript.valueToCode(block, 'to', Blockly.JavaScript.ORDER_ATOMIC); var value_by = Blockly.JavaScript.valueToCode(block, 'by', Blockly.JavaScript.ORDER_ATOMIC); var dropdown_crease = block.getFieldValue('crease'); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); let daishou; if (dropdown_crease == '+') { daishou = '<'; } else { daishou = '>'; } var code = [ `for (${variable_index} = ${value_from}; ${variable_index} ${daishou}= ${value_to}; ${variable_index} ${dropdown_crease}= ${Math.abs(value_by)}) {`, statements_do, `}`, '' ].join('\n'); return code; }; Blockly.Python['ugj_control_for'] = function (block) { var variable_index = Blockly.Python.nameDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE); var value_from = Blockly.Python.valueToCode(block, 'from', Blockly.Python.ORDER_ATOMIC); var value_to = Blockly.Python.valueToCode(block, 'to', Blockly.Python.ORDER_ATOMIC); var value_by = Blockly.Python.valueToCode(block, 'by', Blockly.Python.ORDER_ATOMIC); var dropdown_crease = block.getFieldValue('crease'); var statements_do = Blockly.Python.statementToCode(block, 'do'); if (statements_do === '') statements_do = ' pass'; if (dropdown_crease == '+') { value_by = Math.abs(value_by); value_to++; } else { value_by = Math.abs(value_by) * (-1); value_to--; } var code = [ `for ${variable_index} in range(${value_from}, ${value_to}, ${value_by}) :`, statements_do, '' ].join('\n'); return code; }; var ugjForEachDefinition = { "type": "ugj_controls_foreach", "message0": "%{BKY_UGJ_FOREACH_TITLE}", "args0": [ { "type": "input_value", "name": "list", "check": "Array" }, { "type": "field_variable", "name": "item", "variable": "%{BKY_UGJ_FOREACH_ITEM}" }, { "type": "input_dummy" }, { "type": "input_statement", "name": "do" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "style": "loop_blocks", "tooltip": "%{BKY_UGJ_FOREACH_TOOLTIP}", "helpUrl": "" } Blockly.Blocks['ugj_controls_forEach'] = { init: function () { this.jsonInit(ugjForEachDefinition); } }; Blockly.JavaScript['ugj_controls_forEach'] = function (block) { var value_list = Blockly.JavaScript.valueToCode(block, 'list', Blockly.JavaScript.ORDER_ATOMIC); var variable_item = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('item'), Blockly.Variables.NAME_TYPE); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ `for (let i_index in ${value_list}) {`, `${variable_item} = ${value_list}[i_index];`, statements_do, `}`, '' ].join('\n'); return code; }; Blockly.Python['ugj_controls_forEach'] = function (block) { var value_list = Blockly.Python.valueToCode(block, 'list', Blockly.Python.ORDER_ATOMIC); var variable_item = Blockly.Python.nameDB_.getName(block.getFieldValue('item'), Blockly.Variables.NAME_TYPE); var statements_do = Blockly.Python.statementToCode(block, 'do'); if (value_list === '') value_list = '[]'; if (statements_do === '') statements_do = ' pass'; var code = [ `for ${variable_item} in ${value_list}:`, statements_do, '' ].join('\n'); return code; }; /** Additional Basic Blocks********************************************************************************* */ var ugjCodecharDefinition = { "type": "ugj_codechar", "message0": "%{BKY_UGJ_CODECHAR_TITLE}", "args0": [ { "type": "input_value", "name": "code", "check": "Number" } ], "inputsInline": true, "output": "String", "tooltip": "%{BKY_UGJ_CODECHAR_TOOLTIP}", "helpUrl": "", "style": "text_blocks" }; Blockly.Blocks['ugj_codechar'] = { init: function () { this.jsonInit(ugjCodecharDefinition); } }; Blockly.JavaScript['ugj_codechar'] = function (block) { var value_code = Blockly.JavaScript.valueToCode(block, 'code', Blockly.JavaScript.ORDER_ATOMIC); var code = `String.fromCharCode(${value_code})`; return [code, Blockly.JavaScript.ORDER_NONE]; }; Blockly.Python['ugj_codechar'] = function (block) { var value_code = Blockly.Python.valueToCode(block, 'code', Blockly.Python.ORDER_ATOMIC); var code = `chr(${value_code})`; return [code, Blockly.Python.ORDER_NONE]; }; var ugjCharcodeDefinition = { "type": "ugj_charcode", "message0": "%{BKY_UGJ_CHARCODE_TITLE}", "args0": [ { "type": "input_value", "name": "char", "check": "String" } ], "inputsInline": true, "output": "Number", "tooltip": "%{BKY_UGJ_CHARCODE_TOOLTIP}", "helpUrl": "", "style": "text_blocks" }; Blockly.Blocks['ugj_charcode'] = { init: function () { this.jsonInit(ugjCharcodeDefinition); } }; Blockly.JavaScript['ugj_charcode'] = function (block) { var value_char = Blockly.JavaScript.valueToCode(block, 'char', Blockly.JavaScript.ORDER_ATOMIC); var code = `${value_char}.charCodeAt(0)`; return [code, Blockly.JavaScript.ORDER_NONE]; }; Blockly.Python['ugj_charcode'] = function (block) { var value_char = Blockly.Python.valueToCode(block, 'char', Blockly.Python.ORDER_ATOMIC); var code = `ord(${value_char})`; return [code, Blockly.Python.ORDER_NONE]; }; var ugjHextodecDefinition = { "type": "ugj_hextodec", "message0": "%{BKY_UGJ_HEXTODEC_TITLE}", "args0": [ { "type": "input_value", "name": "hex", "check": "String" } ], "inputsInline": true, "output": "Number", "tooltip": "%{BKY_UGJ_HEXTODEC_TOOLTIP}", "helpUrl": "", "style": "math_blocks" }; Blockly.Blocks['ugj_hextodec'] = { init: function () { this.jsonInit(ugjHextodecDefinition); } }; Blockly.JavaScript['ugj_hextodec'] = function (block) { var value_hex = Blockly.JavaScript.valueToCode(block, 'hex', Blockly.JavaScript.ORDER_ATOMIC); var code = `parseInt (${value_hex}, 16)`; return [code, Blockly.JavaScript.ORDER_ATOMIC]; }; Blockly.Python['ugj_hextodec'] = function (block) { var value_hex = Blockly.Python.valueToCode(block, 'hex', Blockly.Python.ORDER_ATOMIC); var code = `int(${value_hex}, 16)`; return [code, Blockly.Python.ORDER_NONE]; }; var ugjDectohexDefinition = { "type": "ugj_dectohex", "message0": "%{BKY_UGJ_DECTOHEX_TITLE}", "args0": [ { "type": "input_value", "name": "dec", "check": "Number" } ], "inputsInline": true, "output": "String", "tooltip": "%{BKY_UGJ_DECTOHEX_TOOLTIP}", "helpUrl": "", "style": "math_blocks" }; Blockly.Blocks['ugj_dectohex'] = { init: function () { this.jsonInit(ugjDectohexDefinition); } }; Blockly.JavaScript['ugj_dectohex'] = function (block) { var value_dec = Blockly.JavaScript.valueToCode(block, 'dec', Blockly.JavaScript.ORDER_ATOMIC); var code = `'0x' + (${value_dec}).toString(16).toUpperCase()`; return [code, Blockly.JavaScript.ORDER_NONE]; }; Blockly.Python['ugj_dectohex'] = function (block) { var value_dec = Blockly.Python.valueToCode(block, 'dec', Blockly.Python.ORDER_ATOMIC); var code = `'0x' + format(${value_dec}, 'X')`; return [code, Blockly.Python.ORDER_NONE]; }; /** GPIO *****************************************************************************************************/ /************ */ /** GPIO Open */ /************ */ var ugjGpiochipOpenDefinition = { "type": "ugj_gpiochip_open", "message0": "%{BKY_GPIOCHIP_OPEN_TITLE}", "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_GPIOCHIP_OPEN_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_gpiochip_open'] = { init: function () { this.jsonInit(ugjGpiochipOpenDefinition); } }; Blockly.JavaScript['ugj_gpiochip_open'] = function (block) { Blockly.JavaScript.provideFunction_( 'require_oclg', [`const pi = require('@ocogeclub/lgpio');`] ); // var code = `pi.gpio_chip_open(0);\nconsole.log(pi.get_hand());`; // // var code = `var lgHand = pi.gpiochip_open(0);\n`; // var code = `pi.gpiochip_open(0);\n`; // return code; }; Blockly.Python['ugj_gpiochip_open'] = function (block) { Blockly.Python.provideFunction_( 'import_lgpio', ['import lgpio as pi'] ); var code = `lgHand = pi.gpiochip_open(0)\n`; // return code; }; /************* */ /** GPIO Close */ /************* */ var ugjGpiochipCloseDefinition = { "type": "ugj_gpiochip_close", "message0": "%{BKY_GPIOCHIP_CLOSE_TITLE}", "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_GPIOCHIP_CLOSE_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_gpiochip_close'] = { init: function () { this.jsonInit(ugjGpiochipCloseDefinition); } }; Blockly.JavaScript['ugj_gpiochip_close'] = function (block) { var code = 'pi.gpiochip_close();\n'; // var code = 'pi.gpiochip_close(lgHand);\n'; return code; }; Blockly.Python['ugj_gpiochip_close'] = function (block) { var code = 'pi.gpiochip_close(lgHand)\n'; return code; }; /*********************** */ /** GPIO Claim Output ** */ /*********************** */ var ugjGpioClaimOutputDefinition = { "type": "ugj_gpio_claim_output", "message0": "%{BKY_GPIO_CLAIM_OUTPUT_TITLE}", "args0": [ { "type": "input_value", "name": "gpio", "check": "Number" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_GPIO_CLAIM_OUTPUT_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_gpio_claim_output'] = { init: function () { this.jsonInit(ugjGpioClaimOutputDefinition); } }; Blockly.JavaScript['ugj_gpio_claim_output'] = function (block) { var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.gpio_claim_output(${value_gpio});\n`; return code; }; Blockly.Python['ugj_gpio_claim_output'] = function (block) { var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC); var code = `pi.gpio_claim_output(${value_gpio})\n`; return code; }; /********************** */ /** GPIO Claim Input ** */ /********************** */ var ugjGpioClaimInputDefinition = { "type": "ugj_gpio_claim_input", "message0": "%{BKY_GPIO_CLAIM_INPUT_TITLE}", "args0": [ { "type": "input_value", "name": "gpio", "check": "Number" }, { "type": "field_dropdown", "name": "lflag", "options": [ [ "プルアップ", "pi.SET_PULL_UP" ], [ "プルダウン", "pi.SET_PULL_DOWN" ], [ "プル無し", "pi.SET_PULL_NONE" ] ] } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_GPIO_CLAIM_INPUT_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_gpio_claim_input'] = { init: function () { this.jsonInit(ugjGpioClaimInputDefinition); } }; Blockly.JavaScript['ugj_gpio_claim_input'] = function (block) { var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC); var dropdown_lflag = block.getFieldValue('lflag'); var code = `pi.gpio_claim_input(${value_gpio}, ${dropdown_lflag});\n`; return code; }; Blockly.Python['ugj_gpio_claim_input'] = function (block) { var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC); var dropdown_lflag = block.getFieldValue('lflag'); var code = `pi.gpio_claim_input(lgHand, ${value_gpio}, ${dropdown_lflag})\n`; return code; }; /********************* */ /** Read GPIO Value ** */ /***********************/ var ugjGpioReadDefinition = { "type": "ugj_gpio_read", "message0": "%{BKY_GPIO_READ_TITLE}", "args0": [ { "type": "input_value", "name": "gpio", "check": "Number" } ], "inputsInline": true, "output": "Number", "tooltip": "%{BKY_GPIO_READ_TOOLTIP", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_gpio_read'] = { init: function () { this.jsonInit(ugjGpioReadDefinition); } }; Blockly.JavaScript['ugj_gpio_read'] = function (block) { var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.gpio_read(lgHand, ${value_gpio})`; return [code, Blockly.JavaScript.ORDER_NONE]; }; Blockly.Python['ugj_gpio_read'] = function (block) { var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC); var code = `pi.gpio_read(lgHand, ${value_gpio})`; return [code, Blockly.Python.ORDER_NONE]; }; /*******************************************/ /** GPIO Write Value - Common GPIO on/off **/ /*******************************************/ var ugjGpioWriteDefinition = { "type": "ugj_gpio_write", "message0": "%{BKY_GPIO_WRITE_TITLE}", "args0": [ { "type": "input_value", "name": "gpio", "check": "Number" }, { "type": "field_dropdown", "name": "level", "options": [ [ "0", "0" ], [ "1", "1" ] ] } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_GPIO_WRITE_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_gpio_write'] = { init: function () { this.jsonInit(ugjGpioWriteDefinition); } }; Blockly.JavaScript['ugj_gpio_write'] = function (block) { var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC); var dropdown_level = block.getFieldValue('level'); var code = `pi.gpio_write(${value_gpio}, ${dropdown_level});\n`; return code; }; Blockly.Python['ugj_gpio_write'] = function (block) { var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC); var dropdown_level = block.getFieldValue('level'); var code = `pi.gpio_write(lgHand, ${value_gpio}, ${dropdown_level})\n`; return code; }; /*****************/ /** Servo motor **/ /*****************/ var ugjTxServoDefinition = { "type": "ugj_tx_servo", "message0": "%{BKY_TX_SERVO_TITLE}", "args0": [ { "type": "input_value", "name": "gpio", "check": "Number" }, { "type": "input_value", "name": "pulsewidth", "check": "Number" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_TX_SERVO_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_tx_servo'] = { init: function () { this.jsonInit(ugjTxServoDefinition); } }; Blockly.JavaScript['ugj_tx_servo'] = function (block) { var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC); var value_pulsewidth = Blockly.JavaScript.valueToCode(block, 'pulsewidth', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.tx_servo(lgHand, ${value_gpio}, ${value_pulsewidth});\n`; return code; }; Blockly.Python['ugj_tx_servo'] = function (block) { var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC); var value_pulsewidth = Blockly.Python.valueToCode(block, 'pulsewidth', Blockly.Python.ORDER_ATOMIC); var code = `pi.tx_servo(lgHand, ${value_gpio}, ${value_pulsewidth})\n`; return code; }; /************************************************* */ /** starts software timed PWM on an output GPIO ** */ /************************************************* */ var ugjTxPwmDefinition = { "type": "ugj_tx_pwm", "message0": "%{BKY_TX_PWM_TITLE}", "args0": [ { "type": "input_value", "name": "gpio", "check": "Number" }, { "type": "input_value", "name": "pwm_frequency", "check": "Number" }, { "type": "input_value", "name": "pwm_duty_cycle", "check": "Number" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_TX_PWM_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_tx_pwm'] = { init: function () { this.jsonInit(ugjTxPwmDefinition); } }; Blockly.JavaScript['ugj_tx_pwm'] = function (block) { var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC); var value_pwm_frequency = Blockly.JavaScript.valueToCode(block, 'pwm_frequency', Blockly.JavaScript.ORDER_ATOMIC); var value_pwm_duty_cycle = Blockly.JavaScript.valueToCode(block, 'pwm_duty_cycle', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.tx_pwm(lgHand, ${value_gpio}, ${value_pwm_frequency}, ${value_pwm_duty_cycle});\n`; return code; }; Blockly.Python['ugj_tx_pwm'] = function (block) { var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC); var value_pwm_frequency = Blockly.Python.valueToCode(block, 'pwm_frequency', Blockly.Python.ORDER_ATOMIC); var value_pwm_duty_cycle = Blockly.Python.valueToCode(block, 'pwm_duty_cycle', Blockly.Python.ORDER_ATOMIC); var code = `pi.tx_pwm(lgHand, ${value_gpio}, ${value_pwm_frequency}, ${value_pwm_duty_cycle})\n`; return code; }; /********************** */ /** Open Serial Port ** */ /********************** */ var ugjSerialOpenDefinition = { "type": "ugj_serial_open", "message0": "%{BKY_SERIAL_OPEN_TITLE}", "args0": [ // { // "type": "input_value", // "name": "tty", // "check": "String" // }, { "type": "field_dropdown", "name": "baud", "options": [ [ "9600", "9600" ], [ "19200", "19200" ], [ "115200", "115200" ] ] } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_SERIAL_OPEN_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_serial_open'] = { init: function () { this.jsonInit(ugjSerialOpenDefinition); } }; Blockly.JavaScript['ugj_serial_open'] = function (block) { // var value_tty = Blockly.JavaScript.valueToCode(block, 'tty', Blockly.JavaScript.ORDER_ATOMIC); var dropdown_baud = block.getFieldValue('baud'); Blockly.JavaScript.provideFunction_( 'require_oclg', [`const pi = require('@ocogeclub/lgpio');`] ); var code = `pi.serial_open('/dev/serial0', ${dropdown_baud});\n`; return code; }; Blockly.Python['ugj_serial_open'] = function (block) { var value_tty = Blockly.Python.valueToCode(block, 'tty', Blockly.Python.ORDER_ATOMIC); var dropdown_baud = block.getFieldValue('baud'); Blockly.Python.provideFunction_( 'import_lgpio', ['import lgpio as pi'] ); var code = `ser_hand = pi.serial_open(${value_tty}, ${dropdown_baud}, 0)\n`; return code; }; /*********************** */ /** Close Serial Port ** */ /*********************** */ var ugjSerialCloseDefinition = { "type": "ugj_serial_close", "message0": "%{BKY_SERIAL_CLOSE_TITLE}", "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_SERIAL_CLOSE_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_serial_close'] = { init: function () { this.jsonInit(ugjSerialCloseDefinition); } }; Blockly.JavaScript['ugj_serial_close'] = function (block) { var code = 'pi.serial_close();\n'; return code; }; Blockly.Python['ugj_serial_close'] = function (block) { var code = 'pi.serial_close(ser_hand)\n'; return code; }; /************************** */ /** Write Data to Serial ** */ /************************** */ var ugjSerialWriteDefinition = { "type": "ugj_serial_write", "message0": "%{BKY_SERIAL_WRITE_TITLE}", "args0": [ { "type": "input_value", "name": "data", "check": "String" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_SERIAL_WRITE_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_serial_write'] = { init: function () { this.jsonInit(ugjSerialWriteDefinition); } }; Blockly.JavaScript['ugj_serial_write'] = function (block) { var value_data = Blockly.JavaScript.valueToCode(block, 'data', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.serial_write(${value_data});\n`; return code; }; Blockly.Python['ugj_serial_write'] = function (block) { var value_data = Blockly.Python.valueToCode(block, 'data', Blockly.Python.ORDER_ATOMIC); var code = `pi.serial_write(ser_hand, ${value_data}.encode())\n`; return code; }; /************************ */ /** Read Data from Serial */ /************************ */ var ugjSerialReadDefinition = { "type": "ugj_serial_read", "message0": "%{BKY_SERIAL_READ_TITLE}", "args0": [ { "type": "input_value", "name": "count", "check": "Number" } ], "inputsInline": true, "output": null, "tooltip": "%{BKY_SERIAL_READ_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_serial_read'] = { init: function () { this.jsonInit(ugjSerialReadDefinition); } }; Blockly.JavaScript['ugj_serial_read'] = function (block) { var value_count = Blockly.JavaScript.valueToCode(block, 'count', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.serial_read(${value_count})`; return [code, Blockly.JavaScript.ORDER_ATOMIC]; }; Blockly.Python['ugj_serial_read'] = function (block) { var value_count = Blockly.Python.valueToCode(block, 'count', Blockly.Python.ORDER_ATOMIC); var code = `pi.serial_read(ser_hand, ${value_count}).decode()`; return [code, Blockly.Python.ORDER_ATOMIC]; }; /********************* */ /** Open I2C Device ** */ /********************* */ var ugjI2cOpenDefinition = { "type": "ugj_i2c_open", "message0": "%{BKY_I2C_OPEN_TITLE}", "args0": [ { "type": "input_value", "name": "i2c_address", "check": "Number" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_I2C_OPEN_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_i2c_open'] = { init: function () { this.jsonInit(ugjI2cOpenDefinition); } }; Blockly.JavaScript['ugj_i2c_open'] = function (block) { var value_i2c_address = Blockly.JavaScript.valueToCode(block, 'i2c_address', Blockly.JavaScript.ORDER_ATOMIC); Blockly.JavaScript.provideFunction_( 'require_oclg', [`const pi = require('@ocogeclub/lgpio');`] ); var code = `pi.i2c_open(1, ${value_i2c_address});\n`; return code; }; Blockly.Python['ugj_i2c_open'] = function (block) { var value_i2c_address = Blockly.Python.valueToCode(block, 'i2c_address', Blockly.Python.ORDER_ATOMIC); Blockly.Python.provideFunction_( 'import_lgpio', ['import lgpio as pi'] ); var code = `i2c_hand = pi.i2c_open(1, ${value_i2c_address})\n`; return code; }; /********************** */ /** Close I2C Device ** */ /********************** */ var ugjI2cCloseDefinition = { "type": "ugj_i2c_close", "message0": "%{BKY_I2C_CLOSE_TITLE}", "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_I2C_CLOSE_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_i2c_close'] = { init: function () { this.jsonInit(ugjI2cCloseDefinition); } }; Blockly.JavaScript['ugj_i2c_close'] = function (block) { var code = `pi.i2c_close();\n`; return code; }; Blockly.Python['ugj_i2c_close'] = function (block) { var code = `pi.i2c_close(i2c_hand)\n`; return code; }; /****************************************************************** */ /** Writes a single byte to the specified register of the device ** */ /****************************************************************** */ var ugjI2cWriteByteDataDefinition = { "type": "ugj_i2c_write_byte_data", "message0": "%{BKY_I2C_WRITE_BYTE_DATA_TITLE}", "args0": [ { "type": "input_value", "name": "reg", "check": "Number" }, { "type": "input_value", "name": "byte_val", "check": "Number" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_I2C_WRITE_BYTE_DATA_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_i2c_write_byte_data'] = { init: function () { this.jsonInit(ugjI2cWriteByteDataDefinition); } }; Blockly.JavaScript['ugj_i2c_write_byte_data'] = function (block) { var value_reg = Blockly.JavaScript.valueToCode(block, 'reg', Blockly.JavaScript.ORDER_ATOMIC); var value_byte_val = Blockly.JavaScript.valueToCode(block, 'byte_val', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.i2c_write_byte_data(${value_reg}, ${value_byte_val});\n`; return code; }; Blockly.Python['ugj_i2c_write_byte_data'] = function (block) { var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC); var value_byte_val = Blockly.Python.valueToCode(block, 'byte_val', Blockly.Python.ORDER_ATOMIC); var code = `pi.i2c_write_byte_data(i2c_hand, ${value_reg}, ${value_byte_val})\n`; return code; }; /****************************************************************** */ /** Read a single byte from the specified resister of the device ** */ /****************************************************************** */ var ugjI2cReadByteDataDefinition = { "type": "ugj_i2c_read_byte_data", "message0": "%{BKY_I2C_READ_BYTE_DATA_TITLE}", "args0": [ { "type": "input_value", "name": "reg", "check": "Number" } ], "inputsInline": true, "output": null, "tooltip": "%{BKY_I2C_READ_BYTE_DATA_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_i2c_read_byte_data'] = { init: function () { this.jsonInit(ugjI2cReadByteDataDefinition); } }; Blockly.JavaScript['ugj_i2c_read_byte_data'] = function (block) { var value_reg = Blockly.JavaScript.valueToCode(block, 'reg', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.i2c_read_byte_data(${value_reg})\n`; return [code, Blockly.JavaScript.ORDER_ATOMIC]; }; Blockly.Python['ugj_i2c_read_byte_data'] = function (block) { var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC); var code = `pi.i2c_read_byte_data(i2c_hand, ${value_reg})\n`; return [code, Blockly.Python.ORDER_ATOMIC]; }; /************************************************************************** */ /** Returns count bytes read from the raw device associated with handle. ** */ /************************************************************************** */ var ugjI2cReadDeviceDefinition = { "type": "ugj_i2c_read_device", "message0": "%{BKY_I2C_READ_DEVICE_TITLE}", "args0": [ { "type": "input_value", "name": "count", "check": "Number" } ], "inputsInline": true, "output": null, "tooltip": "%{BKY_I2C_READ_DEVICE_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_i2c_read_device'] = { init: function () { this.jsonInit(ugjI2cReadDeviceDefinition); } }; Blockly.JavaScript['ugj_i2c_read_device'] = function (block) { var value_count = Blockly.JavaScript.valueToCode(block, 'count', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.i2c_read_device(${value_count})`; return [code, Blockly.JavaScript.ORDER_ATOMIC]; }; Blockly.Python['ugj_i2c_read_device'] = function (block) { var value_count = Blockly.Python.valueToCode(block, 'count', Blockly.Python.ORDER_ATOMIC); var code = `pi.i2c_read_device(i2c_hand, ${value_count}).decode()`; return [code, Blockly.Python.ORDER_ATOMIC]; }; /********************************************** */ /** Writes the data bytes to the raw device. ** */ /********************************************** */ var ugjI2cWriteDeviceDefinition = { "type": "ugj_i2c_write_device", "message0": "%{BKY_I2C_WRITE_DEVICE_TITLE}", "args0": [ { "type": "input_value", "name": "data", "check": "String" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_I2C_WRITE_DEVICE_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_i2c_write_device'] = { init: function () { this.jsonInit(ugjI2cWriteDeviceDefinition); } }; Blockly.JavaScript['ugj_i2c_write_device'] = function (block) { var value_data = Blockly.JavaScript.valueToCode(block, 'data', Blockly.JavaScript.ORDER_ATOMIC); var code = `pi.i2c_write_device(${value_data})\n`; return code; }; Blockly.Python['ugj_i2c_write_device'] = function (block) { var value_data = Blockly.Python.valueToCode(block, 'data', Blockly.Python.ORDER_ATOMIC); var code = `pi.i2c_write_device(i2c_hand, ${value_data}.encode())\n`; return code; }; /** センサー */ /********* */ /** BME280 */ /********* */ var ugjBme280Definition = { "type": "ugj_bme280", "message0": "%{BKY_UGJ_BME280_TITLE}", "args0": [ { "type": "input_value", "name": "address", "check": "Number" }, { "type": "field_variable", "name": "temp", "variable": "%{BKY_UGJ_BME280_READ_TEMP}" }, { "type": "field_variable", "name": "hum", "variable": "%{BKY_UGJ_BME280_READ_HUM}" }, { "type": "field_variable", "name": "pres", "variable": "%{BKY_UGJ_BME280_READ_PRES}" } ], "inputsInline": true, "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_UGJ_BME280_TOOLTIP}", "helpUrl": "", "style": "gpio_blocks" }; Blockly.Blocks['ugj_bme280'] = { init: function () { this.jsonInit(ugjBme280Definition); } }; Blockly.JavaScript['ugj_bme280'] = function (block) { var value_address = Blockly.JavaScript.valueToCode(block, 'address', Blockly.JavaScript.ORDER_ATOMIC); var variable_temp = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('temp'), Blockly.Variables.NAME_TYPE); var variable_hum = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('hum'), Blockly.Variables.NAME_TYPE); var variable_pres = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('pres'), Blockly.Variables.NAME_TYPE); Blockly.JavaScript.provideFunction_( 'require_bme280', [`const bme280 = require('@ocogeclub/bme280');`] ); var code = [ `const options = {`, ` i2cBusNo: 1,`, ` i2cAddress: ${value_address}`, `};`, `bme280.init(options);`, `let thp = bme280.readSensorData();`, `${variable_temp} = Math.round(thp.temperature_C * 10) / 10;`, `${variable_hum} = Math.round(thp.humidity * 10) / 10;`, `${variable_pres} = Math.round(thp.pressure_hPa);`, `bme280.cancel();`, `` ].join('\n'); return code; }; Blockly.Python['ugj_bme280'] = function (block) { var value_address = Blockly.Python.valueToCode(block, 'address', Blockly.Python.ORDER_ATOMIC); var variable_temp = Blockly.Python.nameDB_.getName(block.getFieldValue('temp'), Blockly.Variables.NAME_TYPE); var variable_hum = Blockly.Python.nameDB_.getName(block.getFieldValue('hum'), Blockly.Variables.NAME_TYPE); var variable_pres = Blockly.Python.nameDB_.getName(block.getFieldValue('pres'), Blockly.Variables.NAME_TYPE); Blockly.Python.provideFunction_( 'import_bme280', [`import BME280`] ); var code = [ `bme280 = BME280.sensor()`, `temp, pres, hum = bme280.read_data()`, `${variable_temp} = round(temp, 1)`, `${variable_hum} = round(hum, 1)`, `${variable_pres} = round(pres/100);`, `bme280.cancel()`, `` ].join('\n'); return code; }; /** Multimedia *****************************************************************************************************/ /******************* */ /** TensorFlow.js ** */ /******************* */ Blockly.Blocks['ugj_library_tensorflow'] = { init: function () { this.appendDummyInput() .appendField("TensorFlowによる画像認識(推論)"); this.setOutput(true, "Library"); this.setStyle('special_blocks') this.setTooltip("tensorflow.jsをロードし、推論ができるようにします。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_library_tensorflow'] = function (block) { var code = `'${ugj_const.library_path}tensorflow.min.js'`; return [code, Blockly.JavaScript.ORDER_NONE]; }; /********************** */ /** Object Detection ** */ /********************** */ Blockly.Blocks['ugj_tfpredict_init'] = { init: function () { this.appendDummyInput() .appendField("画像認識のビデオを表示"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("画像認識(推論)をするためのビデオストリームを表示します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_tfpredict_init'] = function (block) { var code = [ `const video = document.getElementById('subdisplay');`, `video.style.display = 'inline-block';`, `const overlay = document.createElement('canvas');`, `overlay.setAttribute('width', video.width);`, `overlay.setAttribute('height', video.height);`, "const context = overlay.getContext('2d');", "const stream = await navigator.mediaDevices.getUserMedia({ video: {} });", "video.srcObject = stream;", "" ].join('\n'); return code; }; Blockly.Blocks['ugj_tfpredict_loadmodel'] = { init: function () { this.appendDummyInput() .appendField("学習済みの指数えモデル (sign_language_vgg16) を読み込む"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("ardamavi氏による指数え画像データセットをPonDad氏がts.js用モデルにコンバートしたものです。"); this.setHelpUrl("https://github.com/PonDad/manatee"); } }; Blockly.JavaScript['ugj_tfpredict_loadmodel'] = function (block) { var code = [ `const model = await tf.loadModel('${ugj_const.library_path}sign_language_vgg16/model.json');`, "const CLASSES = {0:'zero', 1:'one', 2:'two', 3:'three', 4:'four',5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine'};", "" ].join('\n'); return code; }; Blockly.Blocks['ugj_tfpredict_predict'] = { init: function () { this.appendDummyInput() .appendField("推論をして") .appendField(new Blockly.FieldVariable("結果"), "result") .appendField("を取得する"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("読み込んだモデルを使用してカメラ画像から画像認識を行い、変数に代入します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_tfpredict_predict'] = function (block) { var variable_result = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('result'), Blockly.Variables.NAME_TYPE); var code = [ "context.drawImage(video, 0, 0, video.width, video.height);", "let tensor = tf.fromPixels(canvas).resizeNearestNeighbor([100,100]).toFloat();", "tensor = tensor.div(tf.scalar(255)).expandDims();", "let prediction = await model.predict(tensor).data();", "let results = Array.from(prediction).map(function(p,i){", " return {", " probability: p,", " className: CLASSES[i]", " };", "}).sort(function(a,b){", " return b.probability-a.probability;", "}).slice(0,5);", "let r = '';", "results.forEach(function(p){", " r += `${p.className}:${p.probability.toFixed(6)},`;", "});", `${variable_result} = r;`, "" ].join('\n'); return code; }; /******************** */ /** Face Detection ** */ /******************** */ var with_landmark; var ugjFaceapiDefinition = { "type": "ugj_faceapi", "message0": "%{BKY_UGJ_FACEAPI_TITLE}", "args0": [ { "type": "field_checkbox", "name": "with_landmark", "checked": false }, { "type": "input_dummy" }, { "type": "input_statement", "name": "do" } ], "inputsInline": true, "tooltip": "%{BKY_UGJ_FACEAPI_TOOLTIP}", "helpUrl": "", "style": "multimedia_blocks" }; Blockly.Blocks['ugj_faceapi'] = { init: function () { this.jsonInit(ugjFaceapiDefinition); } }; Blockly.JavaScript['ugj_faceapi'] = function (block) { with_landmark = block.getFieldValue('with_landmark') == 'TRUE'; var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ `require('@tensorflow/tfjs-node');`, `const faceapi = require('@vladmandic/face-api/dist/face-api.node.js');`, statements_do, '' ].join('\n'); return code; }; Blockly.Blocks['ugj_face_init'] = { init: function () { this.appendDummyInput() .appendField("顔検出のビデオを開始"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("顔検出のためのビデオストリームを開始します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_face_init'] = function (block) { var code = [ "const videoEl = document.getElementById('subdisplay');", `const displaySize = { width: videoEl.width, height: videoEl.height };`, "const stream = await navigator.mediaDevices.getUserMedia({ audio: false, video: displaySize });", "videoEl.srcObject = stream;", "" ].join('\n'); return code; }; Blockly.Blocks['ugj_face_display'] = { init: function () { this.appendDummyInput() .appendField("ビデオを表示"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("カメラの映像を画像エリアに表示します。必須ではないブロックです。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_face_display'] = function (block) { var code = [ "videoEl.style.display = 'inline-block';", `const overlay = document.createElement('canvas');`, `overlay.setAttribute('width', videoEl.width);`, `overlay.setAttribute('height', videoEl.height);`, `overlay.className = 'subdisplay';`, `document.getElementById('display_area').appendChild(overlay);`, "" ].join('\n'); return code; }; Blockly.Blocks['ugj_face_detect'] = { init: function () { this.appendDummyInput() .appendField("顔の位置(") .appendField(new Blockly.FieldVariable("左"), "x") .appendField(new Blockly.FieldVariable("上"), "y") .appendField(new Blockly.FieldVariable("幅"), "w") .appendField(new Blockly.FieldVariable("高さ"), "h") .appendField(")を検出したら"); this.appendStatementInput("do") .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("顔を発見したら動作します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_face_detect'] = function (block) { var variable_x = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('x'), Blockly.Variables.NAME_TYPE); var variable_y = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('y'), Blockly.Variables.NAME_TYPE); var variable_w = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('w'), Blockly.Variables.NAME_TYPE); var variable_h = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('h'), Blockly.Variables.NAME_TYPE); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code_model = `await faceapi.nets.tinyFaceDetector.load('${ugj_const.library_path}models/');`; if (with_landmark) { code_model += `\nawait faceapi.nets.faceLandmark68TinyNet.load('${ugj_const.library_path}models/');`; } var code_detect_face = " let result = await faceapi.detectSingleFace(videoEl, options)" if (with_landmark) { code_detect_face += `.withFaceLandmarks(true);` } else { code_detect_face += `;` } var code_rect; if (with_landmark) { code_rect = [ ` ${variable_x} = Math.round(result.detection.box.x);`, ` ${variable_y} = Math.round(result.detection.box.y);`, ` ${variable_w} = Math.round(result.detection.box.width);`, ` ${variable_h} = Math.round(result.detection.box.height);`, ].join('\n'); } else { code_rect = [ ` ${variable_x} = Math.round(result.box.x);`, ` ${variable_y} = Math.round(result.box.y);`, ` ${variable_w} = Math.round(result.box.width);`, ` ${variable_h} = Math.round(result.box.height);`, ].join('\n'); } var code = [ code_model, "const options = new faceapi.TinyFaceDetectorOptions({ inputSize: 128, scoreThreshold : 0.3 });", `const onPlay = async () => {`, // ` const detectInterval = setInterval(async () => {`, code_detect_face, " if (result) {", code_rect, statements_do, " }", // ` }, 500);`, " setTimeout(() => onPlay())", "}", "videoEl.onplay = onPlay;", "" ].join('\n'); return code; }; // Blockly.Blocks['ugj_face_drawrect'] = { init: function () { this.appendDummyInput() .appendField("検出結果を描画"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("ビデオに検出結果を四角や点で表示します。「ビデオを表示」ブロックが必要です。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_face_drawrect'] = function (block) { var code_draw = ` faceapi.draw.drawDetections(overlay, resizedDetections);`; if (with_landmark) { code_draw += `\n faceapi.draw.drawFaceLandmarks(overlay, resizedDetections);`; } var code = [ ` faceapi.matchDimensions(overlay, displaySize);`, ` const resizedDetections = faceapi.resizeResults(result, displaySize);`, code_draw, "" ].join('\n'); return code; }; /**************************** */ /** Say while some seconds ** */ /**************************** */ Blockly.Blocks['ugj_canvas_say'] = { init: function () { this.appendValueInput("say") .setCheck(null); this.appendValueInput("sec") .setCheck("Number") .appendField("と"); this.appendDummyInput() .appendField("秒言う"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("キャンバスにフキダシを作ります。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_say'] = function (block) { var value_say = Blockly.JavaScript.valueToCode(block, 'say', Blockly.JavaScript.ORDER_ATOMIC); var value_sec = Blockly.JavaScript.valueToCode(block, 'sec', Blockly.JavaScript.ORDER_ATOMIC); var code = [ `ugj_fukidashi(String(${value_say}), ${value_sec});`, '' ].join('\n'); return code; }; Blockly.Python['ugj_canvas_say'] = function (block) { var value_say = Blockly.Python.valueToCode(block, 'say', Blockly.Python.ORDER_ATOMIC); var value_sec = Blockly.Python.valueToCode(block, 'sec', Blockly.Python.ORDER_ATOMIC); var code = `print(${value_say})\n`; return code; }; /*************************** */ /** Canvas Initialization ** */ /*************************** */ var ugj_canvas_init_definition = { "type": "ugj_canvas_init", "message0": "%{BKY_UGJ_CANVAS_INIT_TITLE}", "previousStatement": null, "nextStatement": null, "tooltip": "%{BKY_UGJ_CANVAS_INIT_TOOLTIP}", "helpUrl": "", "style": "multimedia_blocks" } Blockly.Blocks['ugj_canvas_init'] = { init: function () { this.jsonInit(ugj_canvas_init_definition); // this.appendDummyInput() // .appendField("キャンバスを表示"); // this.setPreviousStatement(true, null); // this.setNextStatement(true, null); // this.setStyle('multimedia_blocks') // this.setTooltip("キャンバスを表示し、使用できるようにします。"); // this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_init'] = function (block) { var code = [ `let canvas = document.getElementById('gcanvas');`, `canvas.style.display = 'inline-block';`, "let ctx = canvas.getContext('2d');", '' ].join('\n'); return code; }; /************************* */ /** Canvas Finalization ** */ /************************* */ Blockly.Blocks['ugj_canvas_finalize'] = { init: function () { this.appendDummyInput() .appendField("キャンバスを片付ける"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("使ったキャンバスを片付けます。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_finalize'] = function (block) { var code = `document.getElementById('gcanvas').style.display = 'none';\n`; return code; }; /**************************** */ /** Load Image File to Canvas */ /**************************** */ Blockly.Blocks['ugj_canvas_loadimg'] = { init: function () { this.appendValueInput("imgfilename") .setCheck("String") .appendField("ファイル名"); this.appendDummyInput() .appendField("の画像をキャンバスに描画"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("画像ファイルの内容をキャンバス上にロードします。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_loadimg'] = function (block) { var value_imgfilename = Blockly.JavaScript.valueToCode(block, 'imgfilename', Blockly.JavaScript.ORDER_ATOMIC); var code = [ `let img = new Image();`, `img.src = '${ugj_const.doc_root}' + ${value_imgfilename};`, `img.onload = () => ctx.drawImage(img,0,0);`, // `ugj_canvasImg('${ugj_const.doc_root}' + ${value_imgfilename});`, '' ].join('\n'); return code; }; /**************** */ /** Clear Rect ** */ /**************** */ Blockly.Blocks['ugj_canvas_clearrect'] = { init: function () { this.appendValueInput("x") .setCheck("Number") .appendField("長方形に消去:X"); this.appendValueInput("y") .setCheck("Number") .appendField("Y"); this.appendValueInput("w") .setCheck("Number") .appendField("幅"); this.appendValueInput("h") .setCheck("Number") .appendField("高さ"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("長方形に図形を消去します。左上の頂点の座標と、幅・高さを指定します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_clearrect'] = function (block) { var value_x = Blockly.JavaScript.valueToCode(block, 'x', Blockly.JavaScript.ORDER_ATOMIC); var value_y = Blockly.JavaScript.valueToCode(block, 'y', Blockly.JavaScript.ORDER_ATOMIC); var value_w = Blockly.JavaScript.valueToCode(block, 'w', Blockly.JavaScript.ORDER_ATOMIC); var value_h = Blockly.JavaScript.valueToCode(block, 'h', Blockly.JavaScript.ORDER_ATOMIC); var code = `ctx.clearRect(${value_x},${value_y}, ${value_w}, ${value_h});\n`; return code; }; /********************** */ /** Get Canvas Width ** */ /********************** */ Blockly.Blocks['ugj_canvas_width'] = { init: function () { this.appendDummyInput() .appendField("キャンバスの幅"); this.setInputsInline(true); this.setOutput(true, null); this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); this.setStyle('multimedia_blocks') this.setTooltip("キャンバスの幅を取得します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_width'] = function (block) { var code = 'canvas.width'; return [code, Blockly.JavaScript.ORDER_NONE]; }; /*********************** */ /** Get Canvas Height ** */ /*********************** */ Blockly.Blocks['ugj_canvas_height'] = { init: function () { this.appendDummyInput() .appendField("キャンバスの高さ"); this.setInputsInline(true); this.setOutput(true, "Number"); this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); this.setStyle('multimedia_blocks') this.setTooltip("キャンバスの高さを取得します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_height'] = function (block) { var code = 'canvas.height'; return [code, Blockly.JavaScript.ORDER_NONE]; }; /*************************** */ /** Draw Circle on Canvas ** */ /*************************** */ Blockly.Blocks['ugj_canvas_drawcircle'] = { init: function () { this.appendValueInput("x") .setCheck("Number") .appendField("中心の座標 X"); this.appendValueInput("y") .setCheck("Number") .appendField(", Y"); this.appendValueInput("r") .setCheck("Number") .appendField(", 半径"); this.appendValueInput("color") .setCheck("Colour") .appendField(", 塗りつぶしの色"); this.appendDummyInput() .appendField("の円を描画"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("円を描画します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_drawcircle'] = function (block) { var value_x = Blockly.JavaScript.valueToCode(block, 'x', Blockly.JavaScript.ORDER_ATOMIC); var value_y = Blockly.JavaScript.valueToCode(block, 'y', Blockly.JavaScript.ORDER_ATOMIC); var value_r = Blockly.JavaScript.valueToCode(block, 'r', Blockly.JavaScript.ORDER_ATOMIC); var value_color = Blockly.JavaScript.valueToCode(block, 'color', Blockly.JavaScript.ORDER_ATOMIC); var code = [ 'ctx.beginPath();', `ctx.arc(${value_x}, ${value_y}, ${value_r}, 0, Math.PI*2);`, `ctx.fillStyle = ${value_color};`, 'ctx.fill();', 'ctx.closePath();', '' ].join('\n'); return code; }; /************************* */ /** Draw Rect on Canvas ** */ /************************* */ Blockly.Blocks['ugj_canvas_drawrect'] = { init: function () { this.appendValueInput("x") .setCheck("Number") .appendField("左上の座標 (X:"); this.appendValueInput("y") .setCheck("Number") .appendField(", Y:"); this.appendValueInput("w") .setCheck("Number") .appendField("), 幅:"); this.appendValueInput("h") .setCheck("Number") .appendField(", 高さ:"); this.appendValueInput("color") .setCheck("Colour") .appendField(", 塗りつぶしの色:"); this.appendDummyInput() .appendField("の四角形を描画"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("キャンバス上に長方形を描画します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_canvas_drawrect'] = function (block) { var value_x = Blockly.JavaScript.valueToCode(block, 'x', Blockly.JavaScript.ORDER_ATOMIC); var value_y = Blockly.JavaScript.valueToCode(block, 'y', Blockly.JavaScript.ORDER_ATOMIC); var value_w = Blockly.JavaScript.valueToCode(block, 'w', Blockly.JavaScript.ORDER_ATOMIC); var value_h = Blockly.JavaScript.valueToCode(block, 'h', Blockly.JavaScript.ORDER_ATOMIC); var value_color = Blockly.JavaScript.valueToCode(block, 'color', Blockly.JavaScript.ORDER_ATOMIC); var code = [ `ctx.beginPath();`, `ctx.rect(${value_x}, ${value_y}, ${value_w}, ${value_h});`, `ctx.fillStyle = ${value_color};`, `ctx.fill();`, `ctx.closePath();`, '' ].join('\n'); return code; }; /****************************** */ /** KeyUpDown Event Listener ** */ /****************************** */ Blockly.Blocks['ugj_event_key'] = { init: function () { this.appendDummyInput() .appendField("キーボードの") .appendField(new Blockly.FieldVariable("キー"), "key") .appendField("を") .appendField(new Blockly.FieldDropdown([["押したとき", "keydown"], ["離したとき", "keyup"]]), "updown"); this.appendStatementInput("do") .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("キーボードを押したり離したりした時のアクションです。"); this.setHelpUrl("https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent/key/Key_Values"); } }; Blockly.JavaScript['ugj_event_key'] = function (block) { var variable_key = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('key'), Blockly.Variables.NAME_TYPE); var dropdown_updown = block.getFieldValue('updown'); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ `document.addEventListener('${dropdown_updown}', async (e) => {`, ` ${variable_key} = e.key;`, statements_do, `}, false);`, '' ].join('\n'); return code; }; /**************** */ /** Play Sound ** */ /**************** */ Blockly.Blocks['ugj_sound_play'] = { init: function () { this.appendDummyInput() .appendField(new Blockly.FieldDropdown([["ニャー", "meow"], ["コン", "bounce"], ["チン", "type_chime"], ["ディン", "type_dink"], ["タイプ", "type_tap"], ["空白", "type_space"], ["改行", "type_return"]]), "sound") .appendField("の音を鳴らす"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('multimedia_blocks') this.setTooltip("音を鳴らします。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_sound_play'] = function (block) { var dropdown_sound = block.getFieldValue('sound'); var code = `ugj_soundPlay('${dropdown_sound}');\n`; return code; }; /*************************** */ /** Web Speech Recognization */ /*************************** */ Blockly.Blocks['ugj_multimedia_webspeech_recognition'] = { init: function () { this.appendDummyInput() .appendField("音声認識で") .appendField(new Blockly.FieldVariable("ことば"), "transcript") .appendField("を取得する:") .appendField(new Blockly.FieldDropdown([["一回のみ", "once"], ["継続", "continue"]]), "continuous") .appendField(new Blockly.FieldCheckbox("TRUE"), "interim") .appendField("未確定も取得"); this.appendStatementInput("isFinal_do") .setCheck(null) .appendField("確定したら"); this.appendStatementInput("isInterim_do") .setCheck(null) .appendField("未確定なら"); this.appendStatementInput("onStart_do") .setCheck(null) .appendField("開始したら"); this.appendStatementInput("onError_do") .setCheck(null) .appendField("停止したら"); this.setInputsInline(true); this.setPreviousStatement(true); this.setStyle('multimedia_blocks') this.setTooltip("Web Speech API による音声認識を行います。言葉を検知したらステートメントが実行されます。認識途中の暫定結果を取得することもできます。※Web版のみの機能です。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_multimedia_webspeech_recognition'] = function (block) { var variable_transcript = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('transcript'), Blockly.Variables.NAME_TYPE); var dropdown_continuous = block.getFieldValue('continuous'); var checkbox_interim = block.getFieldValue('interim') == 'TRUE'; var statements_isfinal_do = Blockly.JavaScript.statementToCode(block, 'isFinal_do'); var statements_isinterim_do = Blockly.JavaScript.statementToCode(block, 'isInterim_do'); var statements_onStart_do = Blockly.JavaScript.statementToCode(block, 'onStart_do'); var statements_onEnd_do = Blockly.JavaScript.statementToCode(block, 'onError_do'); var code = [ `SpeechRecognition = webkitSpeechRecognition;`, `let recognizer = new SpeechRecognition();`, `recognizer.lang = 'ja-JP';` ].join('\n'); if (dropdown_continuous == 'continue') code += 'recognizer.continuous = true;\n'; if (checkbox_interim == true) code += 'recognizer.interimResults = true;\n'; code += [ `recognizer.onresult = (event) => {`, `let result = event.results[event.resultIndex];`, `${variable_transcript} = result[0].transcript;`, `if (result.isFinal) {`, statements_isfinal_do, `} else {`, statements_isinterim_do, `}`, `}`, `recognizer.onstart = () => {`, statements_onStart_do, `}`, `recognizer.onend = () => {`, statements_onEnd_do, `}`, `recognizer.start();`, '' ].join('\n'); return code; }; /** Network *****************************************************************************************************/ /**************** */ /** TCP/IP Socket */ /**************** */ Blockly.Blocks['ugj_socket'] = { init: function () { this.appendValueInput("host") .setCheck("String") .appendField("ホスト"); this.appendValueInput("port") .setCheck("Number") .appendField("ポート"); this.appendDummyInput() .appendField("で TCP 接続する"); this.appendStatementInput("connect") .setCheck(null) .appendField("接続したら"); this.appendStatementInput("data") .setCheck(null) .appendField(new Blockly.FieldVariable("受信データ"), "data") .appendField("が来たら"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setStyle('network_blocks') this.setTooltip("TCP接続(Telnet)でサーバーと接続します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_socket'] = function (block) { var value_host = Blockly.JavaScript.valueToCode(block, 'host', Blockly.JavaScript.ORDER_ATOMIC); var value_port = Blockly.JavaScript.valueToCode(block, 'port', Blockly.JavaScript.ORDER_ATOMIC); var statements_connect = Blockly.JavaScript.statementToCode(block, 'connect'); var variable_data = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('data'), Blockly.Variables.NAME_TYPE); var statements_data = Blockly.JavaScript.statementToCode(block, 'data'); Blockly.JavaScript.provideFunction_( 'require_net', [`const net = require('net');`] ); var code = [ `var client = net.connect(${value_port}, ${value_host});`, `client.on('connect', async ()=>{`, statements_connect, `}).on('data', async data=>{`, `${variable_data} = data.toString('utf-8', 0, data.length);`, statements_data, `}).on('close', ()=>{`, `console.log('Connection closed.');`, `});`, '' ].join('\n'); return code; }; /*************** */ /** Socket Write */ /*************** */ Blockly.Blocks['ugj_socket_write'] = { init: function () { this.appendValueInput("cmd") .setCheck("String") .appendField("TCP接続に"); this.appendDummyInput() .appendField("を送信する"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("TCP接続で開いたソケットにデータを書き込みます。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_socket_write'] = function (block) { var value_cmd = Blockly.JavaScript.valueToCode(block, 'cmd', Blockly.JavaScript.ORDER_ATOMIC); var code = [ `client.write(${value_cmd});`, '' ].join('\n'); return code; }; /************** */ /** HTTP Server */ /************** */ Blockly.Blocks['ugj_network_httpserver'] = { init: function () { this.appendDummyInput() .appendField("Webサーバを起動してアクセスを待ち、") .appendField(new Blockly.FieldVariable("url"), "URL") .appendField("へアクセスがあったら"); this.appendStatementInput("do") .setCheck(null); this.appendValueInput("response") .setCheck(null) .appendField("最後に"); this.appendDummyInput() .appendField("を表示してアクセス待ちに戻る"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setStyle('network_blocks') this.setTooltip("HTTPサーバを起動します。ポートは3000固定です。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_network_httpserver'] = function (block) { var variable_url = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('URL'), Blockly.Variables.NAME_TYPE); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var value_response = Blockly.JavaScript.valueToCode(block, 'response', Blockly.JavaScript.ORDER_ATOMIC); Blockly.JavaScript.provideFunction_( 'require_http', [`const http = require('http');`] ); var code = [ `let req, res;`, `http.createServer(async (req, res) => {`, `res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });`, `${variable_url} = req.url;`, statements_do, // `res.write('
');`, `res.end(${value_response});`, `}).listen(3000);`, '' ].join('\n'); return code; }; /******************** */ /** axios HTTP client */ /******************** */ // Get URL Blockly.Blocks['ugj_network_axios_geturl'] = { init: function () { this.appendValueInput("url") .setCheck("String") .appendField("URL"); this.appendDummyInput() .appendField("の内容"); this.setInputsInline(true); this.setOutput(true, "String"); this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); this.setStyle('network_blocks') this.setTooltip("URLにGETリクエストを送信し、レスポンスを取得します。エラーの場合、HTTPステータスコードを返します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_network_axios_geturl'] = function (block) { var value_url = Blockly.JavaScript.valueToCode(block, 'url', Blockly.JavaScript.ORDER_ATOMIC); var functionName = Blockly.JavaScript.provideFunction_( 'getUrl', [ `const axios = require('axios');`, 'const ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = async url => {', 'let res, ret;', 'try {', `res = await axios.get(url);`, 'ret = res.data;', '} catch (error) {', 'if (error.response) {', 'ret = error.response.status;', '} else {', 'ret = 999;', '}', '}', 'return ret;', '}' ] ); var code = `await ${functionName}(${value_url})`; return [code, Blockly.JavaScript.ORDER_NONE]; }; /*********** */ /** Sendmail */ /*********** */ Blockly.Blocks['ugj_network_sendmail'] = { init: function () { this.appendValueInput("to") .setCheck("String") this.appendValueInput("subject") .setCheck("String") .appendField("へメールを送信:件名"); this.appendValueInput("text") .setCheck("String") .appendField("本文"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("メールを送信します。Fromアドレスは使用できません。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_network_sendmail'] = function (block) { var value_to = Blockly.JavaScript.valueToCode(block, 'to', Blockly.JavaScript.ORDER_ATOMIC); var value_subject = Blockly.JavaScript.valueToCode(block, 'subject', Blockly.JavaScript.ORDER_ATOMIC); var value_text = Blockly.JavaScript.valueToCode(block, 'text', Blockly.JavaScript.ORDER_ATOMIC); Blockly.JavaScript.provideFunction_( 'require_sendmail', [`const nodemailer = require('nodemailer');`] ); var code = [ `let smtp = nodemailer.createTransport({`, `host: '192.168.0.201',`, `port: 25`, `});`, `let message = {`, `from: 'no-reply@oc.x0.to',`, `to: ${value_to},`, `subject: ${value_subject},`, `text: ${value_text}`, `};`, `try{`, `smtp.sendMail(message, function(error, info){`, `if(error){`, `alert('送信エラー:' + error.message);`, `return;`, `}`, `console.log('send successfully');`, `});`, `} catch(e) {alert('Error: ',e);}`, '' ].join('\n'); return code; }; /********************* */ /** WebRTC Web Chat ** */ /********************* */ // skyway.js Library Blockly.Blocks['ugj_library_skyway'] = { init: function () { this.appendDummyInput() .appendField("WebRTC+SkyWayによるウェブチャット"); this.setInputsInline(true); this.setOutput(true, "Library"); this.setStyle('network_blocks') this.setTooltip("skyway.jsをロードし、ウェブチャットができるようにします。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_library_skyway'] = function (block) { var code = `'${ugj_const.library_path}skyway.js'`; return [code, Blockly.JavaScript.ORDER_NONE]; }; // WebChat Statement Begin Blockly.Blocks['ugj_webchat'] = { init: function () { this.appendDummyInput() .appendField("チャットに必要な部品を表示"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("ビデオ画面、チャット入力フォームや黒板を表示します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_webchat'] = function (block) { var code = [ `const blackboard = document.getElementById('blackboard');`, "blackboard.style.display = 'inline-block';", `const inputForm = document.getElementById('inputForm');`, "inputForm.style.display = 'inline-block';", `const inputBox = document.getElementById('inputBox');`, "inputBox.focus();", "const remoteVideo = document.getElementById('maindisplay');", `remoteVideo.style.display = 'inline-block';`, "const localVideo = document.getElementById('subdisplay');", `localVideo.style.display = 'inline-block';`, `var localStream;`, '' ].join('\n'); return code; }; // getUserMedia Blockly.Blocks['ugj_getusermedia'] = { init: function () { this.appendDummyInput() .appendField("ローカルメディアを開始") this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("このコンピュータにつながれているメディアデバイスから映像を取得して表示します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_getusermedia'] = function (block) { var code = [ `navigator.mediaDevices.getUserMedia({video: true, audio: false})`, ' .then(stream => {', ' localVideo.srcObject = stream;', ' localStream = stream;', ' }).catch( error => {', ' console.error(\'mediaDevice.getUserMedia() error:\', error);', ' return;', ' });', '' ].join('\n'); return code; }; // SkyWay New Peer Blockly.Blocks['ugj_skyway_newpeer'] = { init: function () { this.appendDummyInput() .appendField("SkyWayサーバーに ID:") .appendField(new Blockly.FieldVariable("自分のID"), "my_id") // .appendField(new Blockly.FieldTextInput("MyID"), "NAME") .appendField("で接続する"); this.appendStatementInput("do") .setCheck(null) .appendField("接続したら"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("サーバーにIDを登録して、相手先呼び出しの準備をします。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_skyway_newpeer'] = function (block) { var variable_my_id = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('my_id'), Blockly.Variables.NAME_TYPE); // var text_name = block.getFieldValue('NAME'); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ `const peer = new Peer(${variable_my_id}, {`, " key: window.__SKYWAY_KEY__,", " debug: 3", "});", "peer.on('open', () => {", // ' ugj_blackboardWrite(`SkyWay: "${peer.id}" OK`)', `${variable_my_id} = peer.id;`, "inputForm.addEventListener('submit', onMakeCall);", statements_do, "});", "peer.on('error', err => alert(err.message));", "const onMakeCall = e => {", " e.preventDefault();", " const call = peer.call(inputBox.value, localStream);", " setupCallEventHandlers(call);", " const connect = peer.connect(inputBox.value);", " setupConnectEventHandlers(connect);", " inputBox.value = '';", "}", '' ].join('\n'); return code; }; // Catch Call and Connect Request Blockly.Blocks['ugj_skyway_called'] = { init: function () { this.appendDummyInput() .appendField("チャットに誘われたら応じる"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("接続要求があった場合、チャットを開始する処理です。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_skyway_called'] = function (block) { var code = [ "peer.on('call', call => {", " call.answer(localStream);", " setupCallEventHandlers(call);", "});", "peer.on('connection', connect => {", " setupConnectEventHandlers(connect);", "});", '' ].join('\n'); return code; }; // EventHandlers for Call and Connect Blockly.Blocks['ugj_skyway_events'] = { init: function () { this.appendDummyInput() .appendField(new Blockly.FieldVariable("相手のID"), "remote_id") .appendField("との接続後にすること"); this.appendStatementInput("do") .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("チャットの相手との接続後の動作を定義します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_skyway_events'] = function (block) { var variable_remote_id = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('remote_id'), Blockly.Variables.NAME_TYPE); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ "const setupCallEventHandlers = call => call.on('stream', stream => remoteVideo.srcObject = stream);", "const setupConnectEventHandlers = connect => {", " inputForm.removeEventListener('submit', onMakeCall);", ` ${variable_remote_id} = connect.remoteId;`, statements_do, "}", '' ].join('\n'); return code; }; // Peer Open Blockly.Blocks['ugj_skyway_eventopen'] = { init: function () { this.appendDummyInput() .appendField("接続したらすぐ"); this.appendStatementInput("do") .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("チャット相手との接続が確立したときの動作を決めます。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_skyway_eventopen'] = function (block) { var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ " connect.on('open', () => {", " inputForm.addEventListener('submit', onSendMsg)", statements_do, " });", '' ].join('\n'); return code; }; // Peer Data Receive Blockly.Blocks['ugj_skyway_eventdata'] = { init: function () { this.appendDummyInput() .appendField("相手の") .appendField(new Blockly.FieldVariable("発言"), "data") .appendField("を受けとったら"); this.appendStatementInput("do") .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("チャット相手の発言を受信したときの動作です。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_skyway_eventdata'] = function (block) { var variable_data = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('data'), Blockly.Variables.NAME_TYPE); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ " connect.on('data', data => {", ` ${variable_data} = data;`, statements_do, " });", '' ].join('\n'); return code; }; // Send Message Blockly.Blocks['ugj_skyway_eventsend'] = { init: function () { this.appendDummyInput() .appendField("入力フィールドの") .appendField(new Blockly.FieldVariable("内容"), "data") .appendField("を送信するとき"); this.appendStatementInput("do") .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('network_blocks') this.setTooltip("入力フィールドで送信が発生したときの動作を決めます。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_skyway_eventsend'] = function (block) { var variable_data = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('data'), Blockly.Variables.NAME_TYPE); var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); var code = [ " const onSendMsg = () => {", ` ${variable_data} = inputBox.value;`, ` connect.send(${variable_data});`, " inputBox.value = '';", statements_do, " }", '' ].join('\n'); return code; }; /** Utilitiy Blocks ***********************************************************************************************/ /************ */ /** File Read */ /************ */ Blockly.Blocks['ugj_file_readsync'] = { init: function () { this.appendValueInput("filename") .setCheck("String") .appendField("ファイル"); this.appendDummyInput() .appendField("の内容:符号化") .appendField(new Blockly.FieldDropdown([["utf8", "utf8"], ["base64", "base64"], ["binary", "binary"]]), "encoding"); this.setInputsInline(true); this.setOutput(true, "String"); this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); this.setStyle('special_blocks') this.setTooltip("あなたのホーム/ocogeディレクトリ内にあるファイルの内容を取得します。「符号化」は、テキストファイルでは通常「utf8」を選択します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_file_readsync'] = function (block) { var value_filename = Blockly.JavaScript.valueToCode(block, 'filename', Blockly.JavaScript.ORDER_ATOMIC); var dropdown_encoding = block.getFieldValue('encoding'); let filepath = ugj_const.doc_root + value_filename.replace(/\'/g, ''); Blockly.JavaScript.provideFunction_( 'require_fs', [`const fs = require('fs');`] ); var code = `fs.readFileSync('${filepath}', '${dropdown_encoding}')`; return [code, Blockly.JavaScript.ORDER_ATOMIC]; }; /********************************* */ /** Save TextData to Local Storage */ /********************************* */ Blockly.Blocks['ugj_localstorage_save'] = { init: function () { this.appendValueInput("keyValue") .setCheck("String"); this.appendValueInput("keyName") .setCheck("String") .appendField("をローカルストレージ"); this.appendDummyInput() .appendField("に保存する"); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setStyle('special_blocks') this.setTooltip("テキストデータをローカルストレージに名前を付けて保存します。名前は半角アルファベットと数字だけで指定してください。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_localstorage_save'] = function (block) { var value_keyvalue = Blockly.JavaScript.valueToCode(block, 'keyValue', Blockly.JavaScript.ORDER_ATOMIC); var value_keyname = Blockly.JavaScript.valueToCode(block, 'keyName', Blockly.JavaScript.ORDER_ATOMIC); var code = `localStorage.setItem(${value_keyname}, ${value_keyvalue});\n`; return code; }; /*********************************** */ /** Load Textdata from Local Storage */ /*********************************** */ Blockly.Blocks['ugj_localstorage_load'] = { init: function () { this.appendValueInput("keyName") .setCheck("String") .appendField("ローカルストレージ"); this.appendDummyInput() .appendField("の内容"); this.setInputsInline(true); this.setOutput(true, "String"); this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); this.setStyle('special_blocks') this.setTooltip("ローカルストレージからテキストデータを読み込みます。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_localstorage_load'] = function (block) { var value_keyname = Blockly.JavaScript.valueToCode(block, 'keyName', Blockly.JavaScript.ORDER_ATOMIC); var code = `localStorage.getItem(${value_keyname})`; return [code, Blockly.JavaScript.ORDER_NONE]; }; /**************************** */ /** Key List in Local Storage */ /**************************** */ Blockly.Blocks['ugj_localstorage_keylist'] = { init: function () { this.appendDummyInput() .appendField("ローカルストレージに保存されているデータの一覧"); this.setInputsInline(true); this.setOutput(true, null); this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); this.setStyle('special_blocks') this.setTooltip("ローカルストレージに保存されているキーの一覧を取得します。"); this.setHelpUrl(""); } }; Blockly.JavaScript['ugj_localstorage_keylist'] = function (block) { var functionName = Blockly.JavaScript.provideFunction_( 'localStorage_getKeyList', [ 'const ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = () => {', 'let listArray = [];', 'for (let i=0; i